nur noch eine Tabelle Deck

This commit is contained in:
Andreas Knuth 2024-11-29 17:10:20 +01:00
parent 58d651d981
commit 4f1158c144
1 changed files with 103 additions and 76 deletions

View File

@ -18,7 +18,7 @@ def get_db_connection():
conn.row_factory = sqlite3.Row conn.row_factory = sqlite3.Row
return conn return conn
# Erstellen der Tabellen, falls sie nicht existieren # Erstellen der Tabelle Deck, falls sie nicht existiert
def init_db(): def init_db():
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
@ -26,21 +26,13 @@ def init_db():
cursor.execute(''' cursor.execute('''
CREATE TABLE IF NOT EXISTS Deck ( CREATE TABLE IF NOT EXISTS Deck (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
deckname TEXT UNIQUE NOT NULL deckname TEXT NOT NULL,
)
''')
# Tabelle Image erstellen
cursor.execute('''
CREATE TABLE IF NOT EXISTS Image (
id INTEGER PRIMARY KEY AUTOINCREMENT,
deckid INTEGER,
bildname TEXT, bildname TEXT,
iconindex INTEGER, iconindex INTEGER,
x1 REAL, x1 REAL,
x2 REAL, x2 REAL,
y1 REAL, y1 REAL,
y2 REAL, y2 REAL
FOREIGN KEY(deckid) REFERENCES Deck(id)
) )
''') ''')
conn.commit() conn.commit()
@ -48,7 +40,7 @@ def init_db():
def clean_debug_directories(): def clean_debug_directories():
""" """
Löscht alle Verzeichnisse unter 'debug_images', die keinen Eintrag in der Image-Tabelle haben. Löscht alle Verzeichnisse unter 'debug_images', die keinen Eintrag in der Deck-Tabelle mit bildname haben.
""" """
debug_base_dir = 'debug_images' debug_base_dir = 'debug_images'
if not os.path.exists(debug_base_dir): if not os.path.exists(debug_base_dir):
@ -58,7 +50,7 @@ def clean_debug_directories():
try: try:
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute('SELECT DISTINCT bildname FROM Image') cursor.execute('SELECT DISTINCT bildname FROM Deck WHERE bildname IS NOT NULL')
bildnames = {row['bildname'] for row in cursor.fetchall()} bildnames = {row['bildname'] for row in cursor.fetchall()}
conn.close() conn.close()
except sqlite3.Error as e: except sqlite3.Error as e:
@ -98,65 +90,68 @@ def create_deck():
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
try: try:
# Ein neuer Eintrag für das Deck ohne Bilddaten
cursor.execute('INSERT INTO Deck (deckname) VALUES (?)', (deckname,)) cursor.execute('INSERT INTO Deck (deckname) VALUES (?)', (deckname,))
conn.commit() conn.commit()
deck_id = cursor.lastrowid deck_id = cursor.lastrowid
conn.close() conn.close()
return jsonify({'status': 'success', 'deck_id': deck_id}), 201 return jsonify({'status': 'success', 'deck_id': deck_id}), 201
except sqlite3.IntegrityError: except sqlite3.Error as e:
conn.close() conn.close()
return jsonify({'error': 'Deckname already exists'}), 400 logger.error(f"Datenbankfehler beim Erstellen des Decks: {e}")
return jsonify({'error': 'Database error', 'details': str(e)}), 500
@deck_bp.route('/api/decks', methods=['GET']) @deck_bp.route('/api/decks', methods=['GET'])
def get_decks(): def get_decks():
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
decks = cursor.execute('SELECT * FROM Deck').fetchall() # Alle Einträge abrufen
deck_list = [] entries = cursor.execute('SELECT * FROM Deck').fetchall()
for deck in decks:
deck_id = deck['id']
deck_name = deck['deckname']
# Alle Images für dieses Deck abrufen
images = cursor.execute('''
SELECT
bildname AS name,
iconindex,
x1,
x2,
y1,
y2
FROM Image
WHERE deckid = ?
''', (deck_id,)).fetchall()
images_list = [dict(image) for image in images]
# Deck mit Namen und zugehörigen Images hinzufügen
deck_dict = {
'name': deck_name,
'images': images_list
}
deck_list.append(deck_dict)
conn.close() conn.close()
decks = {}
for entry in entries:
deckname = entry['deckname']
if deckname not in decks:
decks[deckname] = {
'name': deckname,
'images': []
}
if entry['bildname']:
image = {
'name': entry['bildname'],
'iconindex': entry['iconindex'],
'x1': entry['x1'],
'x2': entry['x2'],
'y1': entry['y1'],
'y2': entry['y2']
}
decks[deckname]['images'].append(image)
deck_list = list(decks.values())
return jsonify(deck_list) return jsonify(deck_list)
@deck_bp.route('/api/decks/<deckname>', methods=['DELETE']) @deck_bp.route('/api/decks/<deckname>', methods=['DELETE'])
def delete_deck(deckname): def delete_deck(deckname):
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
# Zuerst die Images löschen, die zu diesem Deck gehören try:
cursor.execute('SELECT id FROM Deck WHERE deckname = ?', (deckname,)) # Überprüfen, ob das Deck existiert
deck = cursor.fetchone() cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ?', (deckname,))
if deck: result = cursor.fetchone()
deck_id = deck['id'] if result['count'] == 0:
cursor.execute('DELETE FROM Image WHERE deckid = ?', (deck_id,)) conn.close()
# Dann das Deck löschen return jsonify({'error': 'Deck not found'}), 404
cursor.execute('DELETE FROM Deck WHERE id = ?', (deck_id,))
# Löschen aller Einträge mit dem gegebenen deckname
cursor.execute('DELETE FROM Deck WHERE deckname = ?', (deckname,))
conn.commit() conn.commit()
conn.close() conn.close()
return jsonify({'status': 'success'}), 200 return jsonify({'status': 'success'}), 200
else: except sqlite3.Error as e:
conn.close() conn.close()
return jsonify({'error': 'Deck not found'}), 404 logger.error(f"Datenbankfehler beim Löschen des Decks '{deckname}': {e}")
return jsonify({'error': 'Database error', 'details': str(e)}), 500
# ------ # ------
# Image - POST, GET, DELETE # Image - POST, GET, DELETE
@ -186,20 +181,24 @@ def update_image():
cursor = conn.cursor() cursor = conn.cursor()
try: try:
# Deck-ID anhand des Decknamens abrufen # Überprüfen, ob das Deck existiert
cursor.execute('SELECT id FROM Deck WHERE deckname = ?', (deckname,)) cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ?', (deckname,))
deck = cursor.fetchone() result = cursor.fetchone()
if not deck: if result['count'] == 0:
conn.close()
return jsonify({'error': 'Deck not found'}), 404 return jsonify({'error': 'Deck not found'}), 404
deck_id = deck['id']
# 1. Lösche alle Einträge für das Deck ohne bildname
cursor.execute('DELETE FROM Deck WHERE deckname = ? AND bildname IS NULL', (deckname,))
inserted_image_ids = [] inserted_image_ids = []
# Durch jede Box iterieren und einen Eintrag in der Image-Tabelle erstellen # 2. Füge neue Image-Einträge hinzu
for index, box in enumerate(boxes): for index, box in enumerate(boxes):
# Überprüfen, ob alle erforderlichen Koordinaten vorhanden sind # Überprüfen, ob alle erforderlichen Koordinaten vorhanden sind
box_fields = ['x1', 'x2', 'y1', 'y2'] box_fields = ['x1', 'x2', 'y1', 'y2']
if not all(field in box for field in box_fields): if not all(field in box for field in box_fields):
conn.close()
return jsonify({'error': 'Missing fields in one of the boxes'}), 400 return jsonify({'error': 'Missing fields in one of the boxes'}), 400
x1 = box['x1'] x1 = box['x1']
@ -207,13 +206,13 @@ def update_image():
y1 = box['y1'] y1 = box['y1']
y2 = box['y2'] y2 = box['y2']
# Setzen des iconindex auf den aktuellen Index der Box # Setzen des iconindex auf den aktuellen Index der Box
iconindex = index iconindex = index
cursor.execute(''' cursor.execute('''
INSERT INTO Image (deckid, bildname, iconindex, x1, x2, y1, y2) INSERT INTO Deck (deckname, bildname, iconindex, x1, x2, y1, y2)
VALUES (?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
''', (deck_id, bildname, iconindex, x1, x2, y1, y2)) ''', (deckname, bildname, iconindex, x1, x2, y1, y2))
inserted_image_ids.append(cursor.lastrowid) inserted_image_ids.append(cursor.lastrowid)
conn.commit() conn.commit()
@ -221,6 +220,7 @@ def update_image():
except sqlite3.Error as e: except sqlite3.Error as e:
conn.rollback() conn.rollback()
logger.error(f"Datenbankfehler beim Aktualisieren der Images für Deck '{deckname}': {e}")
return jsonify({'error': 'Database error', 'details': str(e)}), 500 return jsonify({'error': 'Database error', 'details': str(e)}), 500
finally: finally:
@ -229,7 +229,8 @@ def update_image():
@deck_bp.route('/api/decks/image/<bildname>', methods=['GET']) @deck_bp.route('/api/decks/image/<bildname>', methods=['GET'])
def get_images_by_bildname(bildname): def get_images_by_bildname(bildname):
conn = get_db_connection() conn = get_db_connection()
images = conn.execute('SELECT * FROM Image WHERE bildname = ?', (bildname,)).fetchall() cursor = conn.cursor()
images = cursor.execute('SELECT * FROM Deck WHERE bildname = ?', (bildname,)).fetchall()
conn.close() conn.close()
image_list = [dict(image) for image in images] image_list = [dict(image) for image in images]
return jsonify(image_list) return jsonify(image_list)
@ -237,7 +238,8 @@ def get_images_by_bildname(bildname):
@deck_bp.route('/api/decks/image/<bildname>', methods=['DELETE']) @deck_bp.route('/api/decks/image/<bildname>', methods=['DELETE'])
def delete_images_by_bildname(bildname): def delete_images_by_bildname(bildname):
""" """
Löscht alle Einträge in der Image-Tabelle für den gegebenen bildname. Löscht alle Einträge in der Deck-Tabelle für den gegebenen bildname.
Falls es das letzte Image für ein Deck ist, wird ein neuer Deck-Eintrag erstellt.
Optional: Löscht das zugehörige Debug-Verzeichnis, wenn keine weiteren Einträge bestehen. Optional: Löscht das zugehörige Debug-Verzeichnis, wenn keine weiteren Einträge bestehen.
""" """
try: try:
@ -249,22 +251,41 @@ def delete_images_by_bildname(bildname):
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
# Überprüfen, ob es Einträge mit dem bildname gibt # Start einer Transaktion
cursor.execute('SELECT COUNT(*) as count FROM Image WHERE bildname = ?', (bildname,)) conn.execute('BEGIN')
result = cursor.fetchone()
count = result['count'] if result else 0
if count == 0: # Schritt 1: Identifizieren der betroffenen Decks
cursor.execute('SELECT DISTINCT deckname FROM Deck WHERE bildname = ?', (bildname,))
affected_decks = {row['deckname'] for row in cursor.fetchall()}
if not affected_decks:
conn.close() conn.close()
return jsonify({'error': 'No entries found for the given image name'}), 404 return jsonify({'error': 'No entries found for the given image name'}), 404
# Löschen der Einträge # Schritt 2: Löschen der Image-Einträge
cursor.execute('DELETE FROM Image WHERE bildname = ?', (bildname,)) cursor.execute('DELETE FROM Deck WHERE bildname = ?', (bildname,))
conn.commit() logger.info(f"Alle Einträge für bildname '{bildname}' wurden gelöscht.")
conn.close()
# Optional: Löschen des Debug-Verzeichnisses, wenn keine weiteren Einträge bestehen # Schritt 3: Überprüfen und Wiederherstellen der Deck-Einträge
# Überprüfen, ob das Verzeichnis existiert for deckname in affected_decks:
# Überprüfen, ob noch andere Image-Einträge für dieses Deck existieren
cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildname IS NOT NULL', (deckname,))
result = cursor.fetchone()
image_count = result['count'] if result else 0
if image_count == 0:
# Überprüfen, ob bereits ein Deck-Eintrag existiert
cursor.execute('SELECT COUNT(*) as count FROM Deck WHERE deckname = ? AND bildname IS NULL', (deckname,))
deck_entry = cursor.fetchone()
if deck_entry['count'] == 0:
# Ein neuer Deck-Eintrag wird erstellt
cursor.execute('INSERT INTO Deck (deckname) VALUES (?)', (deckname,))
logger.info(f"Neuer Deck-Eintrag für '{deckname}' erstellt, da keine weiteren Images vorhanden sind.")
# Commit der Transaktion
conn.commit()
# Schritt 4: Optionales Löschen des Debug-Verzeichnisses
debug_dir = os.path.join('debug_images', bildname) debug_dir = os.path.join('debug_images', bildname)
if os.path.exists(debug_dir): if os.path.exists(debug_dir):
try: try:
@ -272,8 +293,7 @@ def delete_images_by_bildname(bildname):
logger.info(f"Debug-Verzeichnis gelöscht: {debug_dir}") logger.info(f"Debug-Verzeichnis gelöscht: {debug_dir}")
except Exception as e: except Exception as e:
logger.error(f"Fehler beim Löschen des Debug-Verzeichnisses '{debug_dir}': {e}") logger.error(f"Fehler beim Löschen des Debug-Verzeichnisses '{debug_dir}': {e}")
# Sie können entscheiden, ob Sie einen Fehler zurückgeben oder nicht # Eine Warnung wird zurückgegeben, aber die Anfrage wird als erfolgreich betrachtet
# Hier geben wir eine Warnung zurück, aber setzen die Anfrage als erfolgreich fort
return jsonify({ return jsonify({
'status': 'success', 'status': 'success',
'message': 'Database entries deleted, but failed to delete debug directory.', 'message': 'Database entries deleted, but failed to delete debug directory.',
@ -283,15 +303,22 @@ def delete_images_by_bildname(bildname):
return jsonify({'status': 'success', 'message': f'All entries for image "{bildname}" have been deleted.'}), 200 return jsonify({'status': 'success', 'message': f'All entries for image "{bildname}" have been deleted.'}), 200
except sqlite3.Error as e: except sqlite3.Error as e:
logger.error(f"Fehler beim Löschen der Image-Einträge für '{bildname}': {e}") # Rollback der Transaktion bei einem Datenbankfehler
conn.rollback()
logger.error(f"Datenbankfehler beim Löschen der Image-Einträge für '{bildname}': {e}")
return jsonify({'error': 'Database error', 'details': str(e)}), 500 return jsonify({'error': 'Database error', 'details': str(e)}), 500
except Exception as e: except Exception as e:
# Rollback der Transaktion bei einem unerwarteten Fehler
conn.rollback()
logger.error(f"Unerwarteter Fehler beim Löschen der Image-Einträge für '{bildname}': {e}") logger.error(f"Unerwarteter Fehler beim Löschen der Image-Einträge für '{bildname}': {e}")
return jsonify({'error': 'Failed to delete image entries', 'details': str(e)}), 500 return jsonify({'error': 'Failed to delete image entries', 'details': str(e)}), 500
finally:
conn.close()
# Sicherstellen, dass die Datenbank existiert # Sicherstellen, dass die Datenbank existiert
if not os.path.exists(DATABASE): if not os.path.exists(DATABASE):
init_db() init_db()
clean_debug_directories() clean_debug_directories()