import os import sys # Ensure the parent directory is in the python path to load app.models parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) if parent_dir not in sys.path: sys.path.insert(0, parent_dir) from app.models import Base from sqlalchemy import MetaData metadata: MetaData = Base.metadata def get_mermaid_type(column_type): """Clean the column type for mermaid ERD compatibility""" t = str(column_type).upper().split('(')[0] return t.replace(' ', '_') def generate_mermaid_erd(metadata: MetaData): lines = ["erDiagram"] # Render tables and columns for table_name, table in sorted(metadata.tables.items()): lines.append(f" {table_name} {{") for column in table.columns: col_type = get_mermaid_type(column.type) constraints = [] if column.primary_key: constraints.append("PK") if column.foreign_keys: constraints.append("FK") # Additional constraint notes notes = '"nullable"' if column.nullable else "" constraints_str = " ".join(constraints) if notes: constraints_str += f" {notes}" lines.append(f" {col_type} {column.name} {constraints_str}") lines.append(" }") # Render relationships for table_name, table in sorted(metadata.tables.items()): for column in table.columns: for fk in column.foreign_keys: target_table = fk.column.table.name # Usually a 1-to-many from target to source in a relational schema lines.append(f" {target_table} ||--o{{ {table_name} : \"{column.name}\"") return "\n".join(lines) def generate_markdown_docs(metadata: MetaData): lines = ["# Documentation du Modèle de Données (Base de Données)\n"] lines.append("Cette documentation a été générée automatiquement à partir des modèles SQLAlchemy.\n") lines.append("## 1. Diagramme Entité-Association (ERD)\n") lines.append("Le schéma ci-dessous montre l'architecture des tables et leurs relations :\n") lines.append("```mermaid") lines.append(generate_mermaid_erd(metadata)) lines.append("```\n") lines.append("## 2. Dictionnaire de Données (Tables)\n") for table_name, table in sorted(metadata.tables.items()): lines.append(f"### Table : `{table_name}`") if table.comment: lines.append(f"> {table.comment}\n") else: lines.append("\n") lines.append("| Colonne | Type | Clé Primaire | Clé Étrangère | Nullable | Défaut |") lines.append("|---------|------|--------------|---------------|----------|--------|") for column in table.columns: col_type = str(column.type) pk = "✅ Oui" if column.primary_key else "-" fk_list = list(column.foreign_keys) if fk_list: fk_target = fk_list[0].column.table.name + "." + fk_list[0].column.name fk = f"🔗 `{fk_target}`" else: fk = "-" nullable = "Oui" if column.nullable else "**Non**" # Format default value safely default_val = "-" if column.default: if column.default.is_scalar: default_val = f"`{column.default.arg}`" elif column.default.is_callable: default_val = "*(auto generate)*" elif column.server_default: default_val = f"`{column.server_default.arg}`" lines.append(f"| `{column.name}` | `{col_type}` | {pk} | {fk} | {nullable} | {default_val} |") lines.append("\n") return "\n".join(lines) if __name__ == "__main__": docs_content = generate_markdown_docs(metadata) docs_dir = os.path.join(parent_dir, 'docs') os.makedirs(docs_dir, exist_ok=True) output_path = os.path.join(docs_dir, 'database_schema.md') with open(output_path, "w", encoding="utf-8") as f: f.write(docs_content) print(f"La documentation a été générée avec succès : {output_path}")