Problem 1: Reimport fails completely (all exercises fail) Root cause: Line 465 existing[0] instead of existing['id'] Fix: Changed to existing['id'] for dict-cursor compatibility Problem 2: 221 exercises skipped, only 2 in database Root cause: Orphaned wiki_import_references from failed imports Fix: New admin endpoint to manually cleanup orphaned references New endpoints: - DELETE /api/import/mediawiki/admin/cleanup-orphaned-references Deletes all references where local_id doesn't exist in target table Returns count of deleted references per type - GET /api/import/mediawiki/admin/stats Shows references vs. actual count + orphaned count Helps diagnose import state issues Usage: 1. Call cleanup endpoint to remove orphaned references 2. Run normal import (reimport=false) 3. Should import all previously failed exercises
96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
"""
|
|
Admin-Hilfsfunktionen für MediaWiki-Import
|
|
"""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from db import get_db, get_cursor
|
|
from routers.import_wiki import require_admin
|
|
|
|
router = APIRouter(prefix="/api/import/mediawiki/admin", tags=["import-admin"])
|
|
|
|
|
|
@router.delete("/cleanup-orphaned-references")
|
|
def cleanup_orphaned_references(session: dict = Depends(require_admin)):
|
|
"""
|
|
Löscht verwaiste Import-Referenzen (Referenz existiert, aber Übung fehlt).
|
|
Nützlich nach fehlgeschlagenen Imports.
|
|
"""
|
|
deleted = {"exercises": 0, "skills": 0, "methods": 0}
|
|
|
|
with get_db() as conn:
|
|
cur = get_cursor(conn)
|
|
|
|
# Exercises
|
|
cur.execute("""
|
|
DELETE FROM wiki_import_references
|
|
WHERE content_type = 'exercise'
|
|
AND local_id NOT IN (SELECT id FROM exercises)
|
|
""")
|
|
deleted["exercises"] = cur.rowcount
|
|
|
|
# Skills
|
|
cur.execute("""
|
|
DELETE FROM wiki_import_references
|
|
WHERE content_type = 'skill'
|
|
AND local_id NOT IN (SELECT id FROM skills)
|
|
""")
|
|
deleted["skills"] = cur.rowcount
|
|
|
|
# Methods
|
|
cur.execute("""
|
|
DELETE FROM wiki_import_references
|
|
WHERE content_type = 'method'
|
|
AND local_id NOT IN (SELECT id FROM training_methods)
|
|
""")
|
|
deleted["methods"] = cur.rowcount
|
|
|
|
conn.commit()
|
|
|
|
return {
|
|
"ok": True,
|
|
"deleted": deleted,
|
|
"message": f"Deleted {sum(deleted.values())} orphaned references"
|
|
}
|
|
|
|
|
|
@router.get("/stats")
|
|
def get_import_stats(session: dict = Depends(require_admin)):
|
|
"""Statistik über Import-Referenzen vs. tatsächliche Einträge."""
|
|
with get_db() as conn:
|
|
cur = get_cursor(conn)
|
|
|
|
# Exercises
|
|
cur.execute("SELECT COUNT(*) as count FROM wiki_import_references WHERE content_type = 'exercise'")
|
|
refs_exercises = cur.fetchone()['count']
|
|
cur.execute("SELECT COUNT(*) as count FROM exercises WHERE import_source = 'mediawiki'")
|
|
actual_exercises = cur.fetchone()['count']
|
|
|
|
# Skills
|
|
cur.execute("SELECT COUNT(*) as count FROM wiki_import_references WHERE content_type = 'skill'")
|
|
refs_skills = cur.fetchone()['count']
|
|
cur.execute("SELECT COUNT(*) as count FROM skills")
|
|
actual_skills = cur.fetchone()['count']
|
|
|
|
# Methods
|
|
cur.execute("SELECT COUNT(*) as count FROM wiki_import_references WHERE content_type = 'method'")
|
|
refs_methods = cur.fetchone()['count']
|
|
cur.execute("SELECT COUNT(*) as count FROM training_methods")
|
|
actual_methods = cur.fetchone()['count']
|
|
|
|
return {
|
|
"exercises": {
|
|
"references": refs_exercises,
|
|
"actual": actual_exercises,
|
|
"orphaned": refs_exercises - actual_exercises
|
|
},
|
|
"skills": {
|
|
"references": refs_skills,
|
|
"actual": actual_skills,
|
|
"orphaned": refs_skills - actual_skills
|
|
},
|
|
"methods": {
|
|
"references": refs_methods,
|
|
"actual": actual_methods,
|
|
"orphaned": refs_methods - actual_methods
|
|
}
|
|
}
|