Skip to content

CLI & Python API

erdify ships a command-line interface, a module entry point, and a Python API for programmatic use.

CLI Options

usage: erdify [-h] [-o OUTPUT] [--title TITLE] [--exclude [PATTERN ...]]
              [--exclude-paths [PATTERN ...]] [--no-default-excludes]
              [--sources [KIND ...]] [--infer-keys] [--django-raw-types]
              [--no-enums] [--no-relationships] [--format FMT [FMT ...]]
              [--check] [-v]
              input

Generate PlantUML ERD diagrams from SQLModel, SQLAlchemy, Django, Pydantic and
dataclass models

positional arguments:
  input                 Directory containing model files (searches for
                        models.py recursively)

options:
  -h, --help            show this help message and exit
  -o, --output OUTPUT   Output .puml file (default: stdout)
  --title TITLE         Diagram title (default: 'Database ERD')
  --exclude [PATTERN ...]
                        Glob patterns (case-sensitive) to exclude entities by
                        class name or table name, e.g. --exclude '*Link'
                        audit_log
  --exclude-paths [PATTERN ...]
                        Glob patterns (case-sensitive) for models.py files to
                        skip before parsing, matched against the path relative
                        to input or any path segment, e.g. --exclude-paths
                        migrations legacy 'apps/experimental/*'
  --no-default-excludes
                        Do not auto-skip models.py under venv/site-
                        packages/cache dirs (.venv, site-packages,
                        __pycache__, ...); scan them too
  --sources [KIND ...]  Restrict which model kinds become entities. Choices:
                        sqlmodel, sqlalchemy, django, dataclass, pydantic.
                        Default: all. e.g. --sources sqlmodel sqlalchemy for
                        DB tables only
  --infer-keys          For keyless models (Pydantic/dataclass), infer a
                        primary key from a field named 'id' and a foreign key
                        from '<x>_id' (target table '<x>')
  --django-raw-types    For Django models, show original field names
                        (CharField, TextField) instead of mapped Python types
                        (str, int, datetime)
  --no-enums            Skip enum definitions in output
  --no-relationships    Skip relationship lines in output
  --format FMT [FMT ...]
                        Output format(s): plantuml (.puml), mermaid (.mmd),
                        json (.json), html (.html). Default: plantuml. With -o
                        the extension is set per format; multiple formats
                        require -o, e.g. --format plantuml mermaid
  --check               Don't write; exit non-zero if the --output file is
                        missing or differs from the freshly generated diagram
                        (for CI / pre-commit drift checks)
  -v, --version         show program's version number and exit

Example: erdify ./src/database -o database_erd.puml

The block above is generated from erdify --help; run python scripts/gen_cli_docs.py after changing CLI flags.

Configuration via pyproject.toml

Instead of passing flags every time, commit them under [tool.erdify] in your project's pyproject.toml. erdify searches upward from the input directory for the nearest pyproject.toml and reads that table.

[tool.erdify]
title = "My Database Schema"
output = "docs/database_erd"        # relative paths resolve from the project root
format = ["plantuml", "mermaid"]    # one or both
sources = ["django"]
exclude = ["audit_log", "*Link"]
exclude_paths = ["migrations", "legacy"]
infer_keys = true
django_raw_types = false

With that in place, erdify . uses these settings. Precedence is explicit CLI flag > [tool.erdify] value > built-in default. (Boolean flags merge by OR: a flag enabled in config can be added to on the CLI but not turned off there.)

Keeping the diagram in sync (--check)

--check regenerates the diagram in memory and compares it to the existing --output file without writing. It exits 0 when they match and non-zero when the file is missing or stale — ideal for CI or a pre-commit hook.

erdify ./src/database -o docs/erd.puml --check

Running as Module

python -m erdify ./src/database -o erd.puml

Python API

from pathlib import Path
from erdify import parse_models_directory, generate_plantuml

# Parse your models
entities, enums = parse_models_directory(Path("./src/database"))

# Generate PlantUML
diagram = generate_plantuml(
    entities=entities,
    enums=enums,
    title="My Database ERD"
)

# Save or use the diagram
Path("erd.puml").write_text(diagram)

Programmatic Access

For lower-level control, use the parser and generator classes directly:

from erdify import (
    ASTDatabaseParser,
    PlantUMLGenerator,
    EntityInfo,
    FieldInfo,
    EnumInfo,
)

# Low-level parser access
parser = ASTDatabaseParser(Path("./models"))
entities, enums = parser.parse_all_models()

# Access entity details
for name, entity in entities.items():
    print(f"Table: {entity.table_name}")
    for field in entity.fields:
        if field.is_primary_key:
            print(f"  PK: {field.name}")
        elif field.is_foreign_key:
            print(f"  FK: {field.name} -> {field.foreign_table}")

# Custom generator with options
generator = PlantUMLGenerator(
    entities=entities,
    enums=enums,
    title="Custom ERD"
)
output = generator.generate()