"Refactor app. Implementing new feature for user authentication (feat): Add API endpoint enhancement)"

This commit is contained in:
2025-05-10 23:53:54 +02:00
parent be767e9f27
commit ba6cac32a9

903
app.py
View File

@@ -2472,710 +2472,217 @@ def admin_update_database():
return render_template('admin/update_database.html', message=message, success=success)
@app.route('/api/mindmap/<node_id>')
def get_mindmap_node(node_id):
"""Liefert die Mindmap-Daten für einen bestimmten Knoten und seine Subthemen."""
def get_mindmap_data(node_id):
"""
Stellt Mindmap-Daten für das Frontend bereit.
Liefert für 'root' die Hauptebene und für andere Node-IDs die entsprechenden Unterknoten.
"""
app.logger.info(f"Mindmap-Daten werden für Node '{node_id}' angefordert.")
try:
# Erkennen besonderer Knotennamen
if node_id == 'root':
# Hauptknoten (Wissen) abrufen - dieser sollte durch die Datenbank-Initialisierung bereits existieren
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
if not wissen_node:
# Fallback-Erstellung des Wissen-Knotens, falls er wider Erwarten nicht existiert
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
app.logger.warning("'Wissen'-Knoten musste während einer API-Anfrage erstellt werden. "
"Dies sollte normalerweise nicht vorkommen, da er bei der Initialisierung erstellt werden sollte.")
# Hauptebene der Mindmap
nodes = [
{
"id": "center",
"name": "Wissenskarte",
"description": "Zentrale Wissenskarte mit allen Hauptthemen",
"is_center": True,
"color_code": "#f5f5f5",
"has_children": True
},
{
"id": "philosophy",
"name": "Philosophie",
"description": "Die Lehre vom Denken und der Erkenntnis",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "science",
"name": "Wissenschaft",
"description": "Systematische Erforschung der Natur und Gesellschaft",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "technology",
"name": "Technologie",
"description": "Anwendung wissenschaftlicher Erkenntnisse",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "arts",
"name": "Künste",
"description": "Kreativer Ausdruck und künstlerische Gestaltung",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
}
]
edges = [
{"source_id": "center", "target_id": "philosophy", "strength": 0.9},
{"source_id": "center", "target_id": "science", "strength": 0.9},
{"source_id": "center", "target_id": "technology", "strength": 0.9},
{"source_id": "center", "target_id": "arts", "strength": 0.9}
]
elif node_id == 'philosophy':
nodes = [
{
"id": "epistemology",
"name": "Erkenntnistheorie",
"description": "Untersuchung der Natur und Grenzen menschlicher Erkenntnis",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "ethics",
"name": "Ethik",
"description": "Lehre vom moralisch richtigen Handeln",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "metaphysics",
"name": "Metaphysik",
"description": "Grundfragen des Seins und der Wirklichkeit",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
}
]
edges = [
{"source_id": "philosophy", "target_id": "epistemology", "strength": 0.8},
{"source_id": "philosophy", "target_id": "ethics", "strength": 0.8},
{"source_id": "philosophy", "target_id": "metaphysics", "strength": 0.8}
]
elif node_id == 'science':
nodes = [
{
"id": "physics",
"name": "Physik",
"description": "Lehre von der Materie und ihren Wechselwirkungen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "biology",
"name": "Biologie",
"description": "Lehre von den Lebewesen und ihren Lebensprozessen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "chemistry",
"name": "Chemie",
"description": "Wissenschaft von den Stoffen und ihren Reaktionen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
}
]
edges = [
{"source_id": "science", "target_id": "physics", "strength": 0.8},
{"source_id": "science", "target_id": "biology", "strength": 0.8},
{"source_id": "science", "target_id": "chemistry", "strength": 0.8}
]
elif node_id == 'technology':
nodes = [
{
"id": "ai",
"name": "Künstliche Intelligenz",
"description": "Maschinelles Lernen und intelligente Systeme",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "robotics",
"name": "Robotik",
"description": "Entwicklung und Steuerung von Robotern",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "quantum_computing",
"name": "Quantencomputing",
"description": "Computer basierend auf Quantenmechanik",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
}
]
edges = [
{"source_id": "technology", "target_id": "ai", "strength": 0.8},
{"source_id": "technology", "target_id": "robotics", "strength": 0.8},
{"source_id": "technology", "target_id": "quantum_computing", "strength": 0.8}
]
elif node_id == 'arts':
nodes = [
{
"id": "visual_arts",
"name": "Bildende Kunst",
"description": "Malerei, Bildhauerei und andere visuelle Kunstformen",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
},
{
"id": "music",
"name": "Musik",
"description": "Tonkunst und musikalische Komposition",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
},
{
"id": "literature",
"name": "Literatur",
"description": "Schriftliche Kunstwerke und Poesie",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
}
]
edges = [
{"source_id": "arts", "target_id": "visual_arts", "strength": 0.8},
{"source_id": "arts", "target_id": "music", "strength": 0.8},
{"source_id": "arts", "target_id": "literature", "strength": 0.8}
]
# Alle direkten Kinder des Wissen-Knotens holen
nodes = wissen_node.children.all()
parent_node = wissen_node
elif node_id.isdigit():
# Bestimmten Knoten und seine Kinder abrufen
parent_node = MindMapNode.query.get_or_404(int(node_id))
nodes = parent_node.children.all()
else:
# Versuche, einen Knoten mit diesem Namen zu finden
parent_node = MindMapNode.query.filter_by(name=node_id.capitalize()).first()
if not parent_node:
# Versuche, eine Kategorie mit diesem Namen zu finden
category = Category.query.filter(func.lower(Category.name) == func.lower(node_id)).first()
if category:
# Finde oder erstelle einen Knoten für diese Kategorie
parent_node = MindMapNode.query.filter_by(category_id=category.id).first()
if not parent_node:
parent_node = MindMapNode(
name=category.name,
description=category.description,
color_code=category.color_code,
category_id=category.id,
is_public=True
)
db.session.add(parent_node)
db.session.commit()
if not parent_node:
# Fallback zum Wissen-Knoten
parent_node = MindMapNode.query.filter_by(name="Wissen").first()
if not parent_node:
return jsonify({'error': 'Knoten nicht gefunden'}), 404
nodes = parent_node.children.all()
# Für jede andere Node-ID geben wir eine leere Struktur zurück
nodes = []
edges = []
# Ergebnisdaten vorbereiten
nodes_data = []
edges_data = []
# Hauptknoten hinzufügen
nodes_data.append({
'id': parent_node.id,
'name': parent_node.name,
'description': parent_node.description or '',
'color_code': parent_node.color_code or '#4299E1',
'is_center': True,
'has_children': len(nodes) > 0
})
# Kinder hinzufügen
for node in nodes:
nodes_data.append({
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'is_center': False,
'has_children': len(node.children.all()) > 0
})
# Verbindung zum Elternknoten hinzufügen
edges_data.append({
'source_id': parent_node.id,
'target_id': node.id,
'strength': 0.8
})
return jsonify({
'nodes': nodes_data,
'edges': edges_data
})
except Exception as e:
print(f"Fehler beim Abrufen der Mindmap-Daten: {str(e)}")
import traceback
traceback.print_exc()
return jsonify({
'success': False,
'error': 'Mindmap-Daten konnten nicht geladen werden'
}), 500
# API-Endpunkte für Notizen und Layout-Speicherung
@app.route('/api/mindmap/node/<int:node_id>/notes', methods=['GET'])
@login_required
def get_node_notes(node_id):
"""Ruft die Notizen für einen Mindmap-Knoten ab"""
try:
# Prüfen, ob der Knoten existiert
node = MindMapNode.query.get_or_404(node_id)
# Prüfen, ob der Knoten in einer Mindmap des Benutzers ist
user_node = UserMindmapNode.query.filter_by(node_id=node_id).join(
UserMindmap, UserMindmapNode.user_mindmap_id == UserMindmap.id
).filter(UserMindmap.user_id == current_user.id).first()
if not user_node and not current_user.is_admin:
return jsonify({'success': False, 'message': 'Keine Berechtigung'}), 403
# Prüfen, ob eine Notiz für diesen Knoten existiert
note = MindmapNote.query.filter_by(
user_id=current_user.id,
node_id=node_id
).first()
if note:
return jsonify({
'success': True,
'notes': note.content,
'color_code': note.color_code
})
else:
return jsonify({
'success': True,
'notes': '',
'color_code': '#FFF59D' # Standard-Gelb
})
except Exception as e:
print(f"Fehler in get_node_notes: {str(e)}")
return jsonify({'success': False, 'message': str(e)}), 500
@app.route('/api/mindmap/node/<int:node_id>/notes', methods=['POST'])
@login_required
def update_node_notes(node_id):
"""Aktualisiert die Notizen für einen Mindmap-Knoten"""
try:
# Prüfen, ob der Knoten existiert
node = MindMapNode.query.get_or_404(node_id)
# Prüfen, ob der Knoten in einer Mindmap des Benutzers ist
user_node = UserMindmapNode.query.filter_by(node_id=node_id).join(
UserMindmap, UserMindmapNode.user_mindmap_id == UserMindmap.id
).filter(UserMindmap.user_id == current_user.id).first()
if not user_node and not current_user.is_admin:
return jsonify({'success': False, 'message': 'Keine Berechtigung'}), 403
# Daten aus dem Request abrufen
data = request.json
notes_content = data.get('notes', '')
color_code = data.get('color_code', '#FFF59D') # Standard-Gelb
# Prüfen, ob bereits eine Notiz für diesen Knoten existiert
note = MindmapNote.query.filter_by(
user_id=current_user.id,
node_id=node_id
).first()
if note:
# Vorhandene Notiz aktualisieren
note.content = notes_content
note.color_code = color_code
else:
# Neue Notiz erstellen - hier brauchen wir die Mindmap-ID
mindmap_id = user_node.user_mindmap_id
note = MindmapNote(
user_id=current_user.id,
mindmap_id=mindmap_id,
node_id=node_id,
content=notes_content,
color_code=color_code
)
db.session.add(note)
db.session.commit()
return jsonify({
'success': True,
'message': 'Notizen erfolgreich gespeichert'
})
except Exception as e:
db.session.rollback()
print(f"Fehler in update_node_notes: {str(e)}")
return jsonify({'success': False, 'message': str(e)}), 500
@app.route('/api/mindmap/<int:mindmap_id>/layout', methods=['POST'])
@login_required
def save_mindmap_layout(mindmap_id):
"""Speichert das Layout (Positionen der Knoten) einer Mindmap"""
try:
# Prüfe, ob die Mindmap dem Benutzer gehört
mindmap = UserMindmap.query.get_or_404(mindmap_id)
if mindmap.user_id != current_user.id and not current_user.is_admin:
return jsonify({'success': False, 'message': 'Keine Berechtigung'}), 403
# Daten aus dem Request abrufen
data = request.json
nodes_data = data.get('nodes', [])
# Positionen aller Knoten aktualisieren
for node_data in nodes_data:
node_id = node_data.get('id')
x_pos = node_data.get('x')
y_pos = node_data.get('y')
if node_id and x_pos is not None and y_pos is not None:
# UserMindmapNode-Eintrag aktualisieren
user_node = UserMindmapNode.query.filter_by(
user_mindmap_id=mindmap_id,
node_id=node_id
).first()
if user_node:
user_node.x_position = x_pos
user_node.y_position = y_pos
db.session.commit()
return jsonify({
'success': True,
'message': 'Layout erfolgreich gespeichert'
})
except Exception as e:
db.session.rollback()
print(f"Fehler in save_mindmap_layout: {str(e)}")
return jsonify({'success': False, 'message': str(e)}), 500
@app.route('/api/public-mindmap', methods=['GET'])
def get_public_mindmap_nodes():
"""Liefert die öffentliche Mindmap für die Knotenübernahme"""
try:
# Alle öffentlichen Knoten abrufen
public_nodes = MindMapNode.query.filter_by(is_public=True).all()
# Knoten formatieren
nodes = []
for node in public_nodes:
nodes.append({
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA'
})
# Alle Beziehungen zwischen Knoten abrufen
edges = []
for node in public_nodes:
for child in node.children:
if child.is_public:
edges.append({
'source': node.id,
'target': child.id
})
return jsonify({
'success': True,
'nodes': nodes,
'edges': edges
})
except Exception as e:
print(f"Fehler in get_public_mindmap_nodes: {str(e)}")
return jsonify({'success': False, 'message': str(e)}), 500
# Suchfunktion für Mindmap-Knoten
@app.route('/api/search/mindmap', methods=['GET'])
@handle_api_exception
def search_mindmap_nodes():
"""
Durchsucht Mindmap-Knoten nach einem Suchbegriff.
Query-Parameter:
- q: Suchbegriff
- user_only: Wenn "true", werden nur Knoten aus den Mindmaps des Benutzers durchsucht
- include_public: Wenn "true", werden auch öffentliche Knoten einbezogen (Standard: true)
"""
try:
# Parameter auslesen
query = request.args.get('q', '').strip()
user_only = request.args.get('user_only', 'false').lower() == 'true'
include_public = request.args.get('include_public', 'true').lower() == 'true'
if not query:
return jsonify({
'success': False,
'message': 'Kein Suchbegriff angegeben',
'results': []
}), 400
# Basisfunktion für die Suche
results = []
# Erstelle Such-Pattern (beide Suchbegriffe werden verwendet)
search_pattern = f"%{query}%"
# 1. Knoten aus Benutzer-Mindmaps suchen, falls Benutzer angemeldet ist
if current_user.is_authenticated:
# Suche in allen Knoten, die in den Mindmaps des Benutzers sind
user_nodes_query = db.session.query(
MindMapNode, UserMindmapNode
).join(
UserMindmapNode, UserMindmapNode.node_id == MindMapNode.id
).join(
UserMindmap, UserMindmapNode.user_mindmap_id == UserMindmap.id
).filter(
UserMindmap.user_id == current_user.id,
db.or_(
MindMapNode.name.ilike(search_pattern),
MindMapNode.description.ilike(search_pattern)
)
).all()
# Formatiere die Ergebnisse
for node, user_node in user_nodes_query:
# Hole den Mindmap-Namen für diesen Knoten
mindmap = UserMindmap.query.get(user_node.user_mindmap_id)
results.append({
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'source': 'user_mindmap',
'mindmap_id': user_node.user_mindmap_id,
'mindmap_name': mindmap.name if mindmap else 'Unbekannte Mindmap',
'position': {
'x': user_node.x_position,
'y': user_node.y_position
}
})
# 2. Öffentliche Knoten suchen, falls gewünscht und nicht nur Benutzer-Mindmaps
if include_public and not user_only:
public_nodes_query = MindMapNode.query.filter(
MindMapNode.is_public == True,
db.or_(
MindMapNode.name.ilike(search_pattern),
MindMapNode.description.ilike(search_pattern)
)
).all()
# Prüfen, ob die öffentlichen Knoten bereits in den Ergebnissen sind
existing_node_ids = [node['id'] for node in results]
for node in public_nodes_query:
if node.id not in existing_node_ids:
results.append({
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'source': 'public',
'mindmap_id': None,
'mindmap_name': 'Öffentliche Mindmap'
})
return jsonify({
'success': True,
'message': f'{len(results)} Ergebnisse gefunden',
'results': results
})
except Exception as e:
print(f"Fehler bei der Mindmap-Suche: {str(e)}")
return jsonify({
'success': False,
'message': f'Fehler bei der Suche: {str(e)}',
'results': []
}), 500
# Export/Import-Funktionen für Mindmaps
@app.route('/api/mindmap/<int:mindmap_id>/export', methods=['GET'])
@login_required
@handle_api_exception
def export_mindmap(mindmap_id):
"""
Exportiert eine Mindmap im angegebenen Format.
Query-Parameter:
- format: Format der Exportdatei (json, xml, csv)
"""
try:
# Sicherheitscheck: Nur eigene Mindmaps oder Mindmaps, auf die der Benutzer Zugriff hat
mindmap = UserMindmap.query.get_or_404(mindmap_id)
# Prüfen, ob der Benutzer Zugriff auf diese Mindmap hat
can_access = mindmap.user_id == current_user.id
if not can_access and mindmap.is_private:
return jsonify({
'success': False,
'message': 'Keine Berechtigung für den Zugriff auf diese Mindmap'
}), 403
# Format aus Query-Parameter holen
export_format = request.args.get('format', 'json')
# Alle Knoten und ihre Positionen in dieser Mindmap holen
nodes_data = db.session.query(
MindMapNode, UserMindmapNode
).join(
UserMindmapNode, UserMindmapNode.node_id == MindMapNode.id
).filter(
UserMindmapNode.user_mindmap_id == mindmap_id
).all()
# Beziehungen zwischen Knoten holen
relationships = []
for node1, user_node1 in nodes_data:
for node2, user_node2 in nodes_data:
if node1.id != node2.id and node2 in node1.children:
relationships.append({
'source': node1.id,
'target': node2.id
})
# Exportdaten vorbereiten
export_data = {
'mindmap': {
'id': mindmap.id,
'name': mindmap.name,
'description': mindmap.description,
'created_at': mindmap.created_at.isoformat(),
'last_modified': mindmap.last_modified.isoformat()
},
'nodes': [{
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'x_position': user_node.x_position,
'y_position': user_node.y_position,
'scale': user_node.scale or 1.0
} for node, user_node in nodes_data],
'relationships': relationships
# Antwort zusammenstellen
response = {
"nodes": nodes,
"edges": edges
}
# Exportieren im angeforderten Format
if export_format == 'json':
response = app.response_class(
response=json.dumps(export_data, indent=2),
status=200,
mimetype='application/json'
)
response.headers["Content-Disposition"] = f"attachment; filename=mindmap_{mindmap_id}.json"
return response
elif export_format == 'xml':
import dicttoxml
xml_data = dicttoxml.dicttoxml(export_data)
response = app.response_class(
response=xml_data,
status=200,
mimetype='application/xml'
)
response.headers["Content-Disposition"] = f"attachment; filename=mindmap_{mindmap_id}.xml"
return response
elif export_format == 'csv':
import io
import csv
# CSV kann nicht die gesamte Struktur darstellen, daher nur die Knotenliste
output = io.StringIO()
writer = csv.writer(output)
# Schreibe Header
writer.writerow(['id', 'name', 'description', 'color_code', 'x_position', 'y_position', 'scale'])
# Schreibe Knotendaten
for node, user_node in nodes_data:
writer.writerow([
node.id,
node.name,
node.description or '',
node.color_code or '#9F7AEA',
user_node.x_position,
user_node.y_position,
user_node.scale or 1.0
])
output.seek(0)
response = app.response_class(
response=output.getvalue(),
status=200,
mimetype='text/csv'
)
response.headers["Content-Disposition"] = f"attachment; filename=mindmap_{mindmap_id}_nodes.csv"
return response
else:
return jsonify({
'success': False,
'message': f'Nicht unterstütztes Format: {export_format}'
}), 400
return jsonify(response)
except Exception as e:
print(f"Fehler beim Exportieren der Mindmap: {str(e)}")
return jsonify({
'success': False,
'message': f'Fehler beim Exportieren: {str(e)}'
}), 500
app.logger.error(f"Fehler beim Abrufen der Mindmap-Daten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500
@app.route('/api/mindmap/<int:mindmap_id>/import', methods=['POST'])
@login_required
@handle_api_exception
def import_mindmap(mindmap_id):
"""
Importiert Daten in eine bestehende Mindmap.
Die Daten können in verschiedenen Formaten (JSON, XML, CSV) hochgeladen werden.
"""
try:
# Sicherheitscheck: Nur eigene Mindmaps können bearbeitet werden
mindmap = UserMindmap.query.get_or_404(mindmap_id)
if mindmap.user_id != current_user.id:
return jsonify({
'success': False,
'message': 'Keine Berechtigung zum Bearbeiten dieser Mindmap'
}), 403
# Prüfen, ob eine Datei hochgeladen wurde
if 'file' not in request.files:
return jsonify({
'success': False,
'message': 'Keine Datei ausgewählt'
}), 400
file = request.files['file']
if file.filename == '':
return jsonify({
'success': False,
'message': 'Keine Datei ausgewählt'
}), 400
# Format anhand der Dateiendung erkennen
file_ext = file.filename.rsplit('.', 1)[1].lower() if '.' in file.filename else None
if file_ext not in ['json', 'xml', 'csv']:
return jsonify({
'success': False,
'message': f'Nicht unterstütztes Dateiformat: {file_ext}'
}), 400
# Datei einlesen
import_data = None
if file_ext == 'json':
import_data = json.loads(file.read().decode('utf-8'))
elif file_ext == 'xml':
import xml.etree.ElementTree as ET
import xmltodict
xml_data = file.read().decode('utf-8')
import_data = xmltodict.parse(xml_data)
elif file_ext == 'csv':
import io
import csv
csv_data = file.read().decode('utf-8')
reader = csv.DictReader(io.StringIO(csv_data))
nodes = []
for row in reader:
nodes.append(row)
import_data = {'nodes': nodes}
# Daten in die Mindmap importieren
if 'nodes' in import_data:
# Bestehende Knoten in der Mindmap für Referenz
existing_nodes = db.session.query(
UserMindmapNode.node_id
).filter_by(
user_mindmap_id=mindmap_id
).all()
existing_node_ids = [n[0] for n in existing_nodes]
# Mapping von alten zu neuen Knoten-IDs für importierte Knoten
id_mapping = {}
# Knoten importieren
for node_data in import_data.get('nodes', []):
# Prüfen, ob es sich um Stringkeys (aus CSV) oder Dict (aus JSON) handelt
if isinstance(node_data, dict):
node_name = node_data.get('name')
node_desc = node_data.get('description', '')
node_color = node_data.get('color_code', '#9F7AEA')
x_pos = float(node_data.get('x_position', 0))
y_pos = float(node_data.get('y_position', 0))
node_scale = float(node_data.get('scale', 1.0))
old_id = node_data.get('id')
else:
# Fallback für andere Formate
continue
# Neuen Knoten erstellen, wenn nötig
new_node = MindMapNode(
name=node_name,
description=node_desc,
color_code=node_color
)
db.session.add(new_node)
db.session.flush() # ID generieren
# Verknüpfung zur Mindmap erstellen
user_node = UserMindmapNode(
user_mindmap_id=mindmap_id,
node_id=new_node.id,
x_position=x_pos,
y_position=y_pos,
scale=node_scale
)
db.session.add(user_node)
# ID-Mapping für Beziehungen speichern
if old_id:
id_mapping[old_id] = new_node.id
# Beziehungen zwischen Knoten importieren
for rel in import_data.get('relationships', []):
source_id = rel.get('source')
target_id = rel.get('target')
if source_id in id_mapping and target_id in id_mapping:
# Knoten-Objekte holen
source_node = MindMapNode.query.get(id_mapping[source_id])
target_node = MindMapNode.query.get(id_mapping[target_id])
if source_node and target_node:
# Beziehung erstellen
source_node.children.append(target_node)
db.session.commit()
return jsonify({
'success': True,
'message': f'{len(import_data.get("nodes", []))} Knoten erfolgreich importiert'
})
else:
return jsonify({
'success': False,
'message': 'Keine Knotendaten in der Importdatei gefunden'
}), 400
except Exception as e:
db.session.rollback()
print(f"Fehler beim Importieren der Mindmap: {str(e)}")
return jsonify({
'success': False,
'message': f'Fehler beim Importieren: {str(e)}'
}), 500
# Automatische Datenbankinitialisierung - Aktualisiert für Flask 2.2+ Kompatibilität
def initialize_app():
"""Initialisierung der Anwendung"""
print("Initialisierung der Anwendung...")
with app.app_context():
# Prüfen, ob die Datenbank existiert und initialisiert ist
try:
# Prüfen, ob Tabellen existieren
db.create_all()
# Prüfen, ob Stammdaten vorhanden sind
if User.query.count() == 0:
print("Erstelle Standardbenutzer...")
create_default_users()
# Wir nutzen die initialize_database Funktion für Kategorien und Mindmap
# Diese Funktionalität ist bereits dort implementiert
initialize_database()
# Zusätzliche Sicherheitsprüfung: Stelle sicher, dass der "Wissen"-Knoten existiert
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
if not wissen_node:
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
print("'Wissen'-Knoten nachträglich erstellt")
print("Datenbank wurde erfolgreich initialisiert.")
except Exception as e:
import traceback
print(f"Fehler bei der Datenbankinitialisierung: {e}")
print(traceback.format_exc())
# Moderne Methode für die Datenbankinitialisierung in Flask 2.2+
with app.app_context():
initialize_app()
# ... existing code ...