ErdDocs

SQLAlchemy models to ER diagram

Paste your models and get the ER diagram of the tables they map to — table names from __tablename__, relations from ForeignKey. No pip install, no Graphviz binary, no database connection: the file is read in your browser and never uploaded.

Your schema

The example mixes both declaration styles on purpose. Paste your own models.py over it.

Both styles, including a file that mixes them

SQLAlchemy has two ways to declare a column and both are everywhere: the classic assignment and the 2.0 annotated form. A codebase part-way through a migration contains both, often in the same file, which is exactly what the example above does — four classic models and one written the new way.

  • Classic — email = Column(String(160), nullable=False, unique=True). Type, flags and comment all live in the call.
  • 2.0 — notes: Mapped[Optional[str]] = mapped_column(Text). The annotation carries the nullability, so Optional is read as a nullable column even though nothing says nullable=True.

No install, and the file does not have to import

ErdDocs reads the models as text in a browser tab, so there is nothing to install and no Graphviz to find. eralchemy, the standard answer to this question, is a good tool — it is also a Python package that wants a system Graphviz binary to render anything, which is a small ask inside a project you own and a much larger one on a machine you do not administer, or when the models arrived as an attachment and you just want to see the shape of them.

ErdDocs does not execute your code either. The models are read as text, so a file that would not import — missing dependency, half-finished refactor, a snippet copied out of a review — still draws. That is a different guarantee from "runs your models and inspects the metadata", and on a work laptop it is usually the one that matters.

What ends up in the diagram

  • Tables, not classes — __tablename__ wins, so class Company is drawn as companies.
  • Real relations — ForeignKey("jobs.id") becomes a solid line. relationship() is not a column and is not drawn as one; the foreign key column next to it is what the database actually has.
  • The properties a reviewer asks about — primary keys, autoincrement, nullability, unique constraints, defaults and server_default, with comment= text becoming the description in the data dictionary.

FAQ

Does it read the 2.0 style as well as the classic one?

Both, including a file that mixes them. The classic id = Column(Integer, primary_key=True) and the 2.0 id: Mapped[int] = mapped_column(primary_key=True) are read the same way, and in the 2.0 style the annotation is used where the call leaves something out — Mapped[Optional[str]] means the column is nullable even when nullable= is not written.

Do I need Graphviz or pip install anything?

No. ErdDocs reads the models as text you paste into a browser tab — no pip, no PATH, no binary. eralchemy, the usual answer for this job, is a Python package that also needs a system Graphviz binary on the PATH to render: reasonable in a project you own, awkward on a locked-down laptop or when you were handed models.py by someone else.

What does it take from the models?

__tablename__ as the table name, columns with the SQL type the model asks for, primary keys, autoincrement, nullable and unique flags, server_default and default values, comment= text as the description, and ForeignKey("table.column") as a real relation. relationship() is not a column and is not drawn as one — the foreign key column beside it is what the database has.

What about models spread over many files?

Paste them one after another into the same panel. ErdDocs reads classes, not modules, so several files concatenated behave exactly like one file — which is usually faster than arranging imports for a tool that wants to execute your code. ErdDocs never executes yours: the models are read as text, so a file that would not import still produces a diagram.

Is it free?

Drawing and exporting the picture are free, no account, for schemas up to 25 tables. $9 once lifts the limit and unlocks the data dictionary — the document form, with every column, type, default and index listed.

Related