Entity relationship diagrams for Python data model classes like Pydantic.
npx @tessl/cli install tessl/pypi-erdantic@1.1.0Erdantic is a Python library for automatically generating entity relationship diagrams (ERDs) from Python data model classes. It supports multiple popular data modeling frameworks including Pydantic V2, Pydantic V1 legacy, attrs, msgspec, and Python standard library dataclasses. The library uses Graphviz for rendering high-quality diagrams and offers both a convenient CLI interface and a comprehensive Python API for programmatic use.
The tool is particularly valuable for documentation purposes, allowing developers to visualize relationships between data models in their applications with clean, professional diagrams. It features automatic discovery of model relationships, customizable diagram styling, and support for complex nested data structures.
pip install erdanticimport erdanticfrom erdantic import EntityRelationshipDiagram, create, draw, to_dotThe most common use case is generating diagrams from data model classes using the convenience functions:
from pydantic import BaseModel
from erdantic import draw
class User(BaseModel):
name: str
email: str
class Post(BaseModel):
title: str
author: User
tags: list[str]
# Generate and save diagram
draw(User, Post, out="my_models.png")For programmatic control, use the main diagram class:
from erdantic import EntityRelationshipDiagram
# Create diagram instance
diagram = EntityRelationshipDiagram()
diagram.add_model(User)
diagram.add_model(Post)
# Render to file
diagram.draw("output.svg")
# Get DOT language representation
dot_string = diagram.to_dot()Erdantic's architecture consists of several key components:
EntityRelationshipDiagram manages model information and relationshipscreate, draw, to_dot) for common operationsCreate and manage entity relationship diagrams programmatically. The core EntityRelationshipDiagram class provides methods to add models, analyze relationships, and maintain diagram state.
class EntityRelationshipDiagram:
def add_model(self, model: type, recurse: bool = True) -> None:
"""Add a data model class to the diagram."""
def draw(self, out: Union[str, os.PathLike], graph_attr: Optional[Mapping[str, Any]] = None,
node_attr: Optional[Mapping[str, Any]] = None, edge_attr: Optional[Mapping[str, Any]] = None, **kwargs) -> None:
"""Render entity relationship diagram to file."""
def to_dot(self, graph_attr: Optional[Mapping[str, Any]] = None, node_attr: Optional[Mapping[str, Any]] = None,
edge_attr: Optional[Mapping[str, Any]] = None) -> str:
"""Generate DOT language representation of diagram."""High-level functions for quick diagram generation without managing diagram instances directly. These functions automatically create diagrams, analyze models, and produce output.
def create(*models_or_modules: Union[type, ModuleType], terminal_models: Collection[type] = tuple(),
termini: Collection[type] = tuple(), limit_search_models_to: Optional[Collection[str]] = None) -> EntityRelationshipDiagram:
"""Construct EntityRelationshipDiagram from given data model classes or modules."""
def draw(*models_or_modules: Union[type, ModuleType], out: Union[str, os.PathLike],
terminal_models: Collection[type] = tuple(), termini: Collection[type] = tuple(),
limit_search_models_to: Optional[Collection[str]] = None,
graph_attr: Optional[Mapping[str, Any]] = None, node_attr: Optional[Mapping[str, Any]] = None,
edge_attr: Optional[Mapping[str, Any]] = None, **kwargs) -> None:
"""Render entity relationship diagram for given data model classes to file."""
def to_dot(*models_or_modules: Union[type, ModuleType], terminal_models: Collection[type] = [],
termini: Collection[type] = tuple(), limit_search_models_to: Optional[Collection[str]] = None,
graph_attr: Optional[Mapping[str, Any]] = None, node_attr: Optional[Mapping[str, Any]] = None,
edge_attr: Optional[Mapping[str, Any]] = None) -> str:
"""Generate DOT language representation of entity relationship diagram."""Extensible framework for supporting different data modeling libraries. Plugins provide predicates to identify model types and extractors to analyze model fields.
def list_plugins() -> list[str]:
"""List the keys of all registered plugins."""Command-line tool for generating diagrams from fully qualified model/module names. Supports various output formats and customization options.
# CLI entry point: erdantic [models_or_modules...] --out OUTPUT_FILE [options]Internal data structures representing analyzed models, fields, and relationships. These classes provide the foundation for diagram generation and can be used for advanced programmatic manipulation.
class ModelInfo:
full_name: FullyQualifiedName
name: str
fields: dict[str, FieldInfo]
description: str
class FieldInfo:
model_full_name: FullyQualifiedName
name: str
type_name: str
class Edge:
source_model_full_name: FullyQualifiedName
source_field_name: str
target_model_full_name: FullyQualifiedName
target_cardinality: Cardinality
target_modality: ModalityException classes that provide specific error information when operations fail. Essential for error handling and troubleshooting issues with model analysis and diagram generation.
class ErdanticException(Exception): ...
class UnknownModelTypeError(ValueError, ErdanticException): ...
class PluginNotFoundError(KeyError, ErdanticException): ...
class ModelOrModuleNotFoundError(ImportError, ErdanticException): ...
class UnresolvableForwardRefError(NameError, ErdanticException): ...
class UnevaluatedForwardRefError(ErdanticException): ...
class FieldNotFoundError(AttributeError, ErdanticException): ...