Frameworks Overview¶
erdify recognizes five model frameworks from source and renders them into the same ERD format. This page shows the five frameworks side by side, how each is detected, and a worked example with the generated PlantUML. For Django-specific parsing details see Django ORM.
One Schema, Five Frameworks¶
The snippets below all describe the same User / Order schema — only the
syntax differs. Each one produces the identical diagram:

Info
The SQLModel, SQLAlchemy and Django versions declare keys explicitly (Django
via its implicit id and ForeignKey). Pydantic and dataclasses have no key
concept, so they are rendered with --infer-keys
(id → PK, <x>_id → FK) to match. The runnable sources live in
docs/examples/.
| SQLModel | SQLAlchemy 2.0 |
|---|---|
|
|
Pydantic --infer-keys | Dataclass --infer-keys |
|
|
| Django ORM | |
| |
How each framework is detected & parsed¶
| Framework | Detected by | Keys | Relationships |
|---|---|---|---|
| SQLModel | table=True |
Field(primary_key=…, foreign_key=…) |
Relationship() |
| SQLAlchemy 2.0 | __tablename__ + Mapped[...] columns |
mapped_column(primary_key=…), ForeignKey(...) |
relationship() (lowercase) |
| Django ORM | models.Model subclass |
primary_key=True or implicit id, ForeignKey/OneToOneField |
ForeignKey (N:1), OneToOneField (1:1), ManyToManyField (M:N, incl. through=) |
| Pydantic | BaseModel subclass (incl. transitive) |
--infer-keys only |
nested model refs (user: User, list["Order"]) |
| Dataclass | @dataclass decorator |
--infer-keys only |
nested model refs |
Info
Mixins / abstract bases (e.g. a SQLAlchemy mixin without __tablename__, or a
Django class Meta: abstract = True base) are not drawn as tables, but their
columns are inherited into concrete entities.
Worked example¶
Given these SQLModel definitions:
from enum import Enum
from sqlmodel import SQLModel, Field, Relationship
class UserRole(Enum):
ADMIN = "admin"
USER = "user"
class User(SQLModel, table=True):
__tablename__: str = "user"
id: int = Field(primary_key=True)
name: str
email: str = Field(index=True)
role: UserRole = Field(default=UserRole.USER)
orders: list["Order"] = Relationship(back_populates="user")
class Order(SQLModel, table=True):
__tablename__: str = "order"
id: int = Field(primary_key=True)
user_id: int = Field(foreign_key="user.id")
total: float
user: "User" = Relationship(back_populates="orders")
The tool generates:

with following code:
@startuml Database ERD
!define primary_key(x) <b><color:#b8861b><&key></color> x</b>
!define foreign_key(x) <color:#aaaaaa><&key></color> x
!define column(x) <color:#efefef><&media-record></color> x
skinparam linetype ortho
' Enums
enum UserRole << (E,#FFCC00) >> {
ADMIN
USER
}
' Entities
entity "user" as User {
primary_key(id) : int
column(name) : str
column(email) : str
column(role) : UserRole = USER
}
entity "order" as Order {
primary_key(id) : int
foreign_key(user_id) : int
column(total) : float
}
' Relationships
Order }o--|| User : "user_id"
@enduml