first commit
Build and deploy / build-and-push (push) Successful in 17s
Build and deploy / deploy (push) Successful in 10s

This commit is contained in:
william
2026-08-21 16:23:49 +02:00
committed by william
commit 3f4ebc4527
248 changed files with 10180 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
"""Lignes de données (CRUD) pour les objets définis dans un jeu."""
+8
View File
@@ -0,0 +1,8 @@
from ..connection import connect
def delete_row(slug, definition, row_id):
conn = connect(slug)
conn.execute(f"DELETE FROM {definition['table_name']} WHERE id = ?", (row_id,))
conn.commit()
conn.close()
+10
View File
@@ -0,0 +1,10 @@
from ..connection import connect
def get_row(slug, definition, row_id):
conn = connect(slug)
row = conn.execute(
f"SELECT * FROM {definition['table_name']} WHERE id = ?", (row_id,)
).fetchone()
conn.close()
return dict(row) if row else None
+14
View File
@@ -0,0 +1,14 @@
from ..connection import connect
from .row_columns_and_values import row_columns_and_values
def insert_row(slug, definition, form_data):
"""Feature 3 : enregistre en base les données saisies dans le formulaire
généré à partir de la définition d'objet."""
cols, values = row_columns_and_values(definition, form_data)
conn = connect(slug)
placeholders = ["?"] * len(cols)
sql = f"INSERT INTO {definition['table_name']} ({', '.join(cols)}) VALUES ({', '.join(placeholders)})"
conn.execute(sql, values)
conn.commit()
conn.close()
+8
View File
@@ -0,0 +1,8 @@
from ..connection import connect
def list_rows(slug, definition):
conn = connect(slug)
rows = conn.execute(f"SELECT * FROM {definition['table_name']} ORDER BY id DESC").fetchall()
conn.close()
return [dict(r) for r in rows]
+19
View File
@@ -0,0 +1,19 @@
from ..connection import connect
from ..slugify import slugify
from ..definitions.get_definition import get_definition
def relation_options(slug, related_definition_id):
"""Lignes existantes d'un objet lié, pour peupler un <select> de relation."""
related = get_definition(slug, related_definition_id)
conn = connect(slug)
rows = conn.execute(f"SELECT * FROM {related['table_name']} ORDER BY id").fetchall()
conn.close()
display_field = related["fields"][0]["name"] if related["fields"] else "id"
display_col = slugify(display_field).replace("-", "_")
options = []
for r in rows:
r = dict(r)
label = r.get(display_col, f"#{r['id']}")
options.append({"id": r["id"], "label": f"{label} (#{r['id']})"})
return options
+26
View File
@@ -0,0 +1,26 @@
from ..slugify import slugify
def row_columns_and_values(definition, form_data):
"""Traduit les données d'un formulaire généré en (colonnes, valeurs)
prêtes pour un INSERT ou un UPDATE — factorisé pour que les deux
partagent exactement la même logique de conversion de type."""
cols, values = [], []
for f in definition["fields"]:
fname = slugify(f["name"]).replace("-", "_")
if f["type"] == "relation":
col = f"{fname}_id"
raw = form_data.get(col, "")
values.append(int(raw) if raw else None)
elif f["type"] == "booleen":
values.append(1 if form_data.get(fname) == "on" else 0)
col = fname
elif f["type"] in ("nombre_entier", "nombre_decimal"):
raw = form_data.get(fname, "")
values.append((int(raw) if f["type"] == "nombre_entier" else float(raw)) if raw != "" else None)
col = fname
else:
values.append(form_data.get(fname, "") or None)
col = fname
cols.append(col)
return cols, values
+26
View File
@@ -0,0 +1,26 @@
from ..connection import connect
from ..slugify import slugify
from ..definitions.definitions_referencing import definitions_referencing
from ..definitions.get_definition import get_definition
def rows_referencing(slug, definition_id, row_id):
"""Pour l'écran de suppression d'une ligne : liste, pour chaque objet
qui a une relation vers l'objet de cette ligne, combien de ses lignes
pointent vers CETTE ligne précise — pour avertir avant une suppression
qui laisserait des relations orphelines (aucune suppression en cascade
n'est faite automatiquement, par sécurité)."""
refs = []
for d in definitions_referencing(slug, definition_id):
full = get_definition(slug, d["id"])
for f in full["fields"]:
if f["type"] == "relation" and f["relation_definition_id"] == definition_id:
col = slugify(f["name"]).replace("-", "_") + "_id"
conn = connect(slug)
count = conn.execute(
f"SELECT COUNT(*) AS c FROM {full['table_name']} WHERE {col} = ?", (row_id,)
).fetchone()["c"]
conn.close()
if count:
refs.append({"definition_name": full["name"], "field_name": f["name"], "count": count})
return refs
+16
View File
@@ -0,0 +1,16 @@
from ..connection import connect
from .row_columns_and_values import row_columns_and_values
def update_row(slug, definition, row_id, form_data):
"""CRUD — Update : ré-enregistre une ligne existante avec les nouvelles
valeurs saisies dans le même formulaire généré que pour la création."""
cols, values = row_columns_and_values(definition, form_data)
conn = connect(slug)
set_clause = ", ".join(f"{c} = ?" for c in cols)
conn.execute(
f"UPDATE {definition['table_name']} SET {set_clause} WHERE id = ?",
values + [row_id],
)
conn.commit()
conn.close()
+15
View File
@@ -0,0 +1,15 @@
from ..connection import connect
from ..slugify import slugify
def update_row_field(slug, definition, row_id, field_def, new_value):
"""Met à jour UNE SEULE colonne d'une ligne existante — utilisé par les
actions "Modifier une donnée" du mode jouable, qui ne doivent jamais
écraser les autres champs de la ligne (contrairement à update_row, qui
attend un formulaire complet)."""
fname = slugify(field_def["name"]).replace("-", "_")
col = f"{fname}_id" if field_def["type"] == "relation" else fname
conn = connect(slug)
conn.execute(f"UPDATE {definition['table_name']} SET {col} = ? WHERE id = ?", (new_value, row_id))
conn.commit()
conn.close()