Skip to main content

Pydantic2Django: The Bridge Between Python Objects and the Django ORM

A powerful utility for generating Django models from Pydantic models, Python dataclasses, and even generic Python classes, and providing seamless, bidirectional data conversion between them.

Overview

Pydantic2Django bridges the gap between your application's data layer (defined using Pydantic, dataclasses, etc.) and your persistence layer in Django. It allows you to:

  1. Generate models.py files automatically from your existing Python classes.
  2. Convert data seamlessly between Django model instances and your source Pydantic/dataclass objects.
  3. Persist and manage application data objects in a Django database without writing boilerplate mapping code.
  4. Handle relationships between your Python objects and translate them into Django's relational fields (ForeignKey, ManyToManyField).

This library supports:

  • Pydantic Models: Robust support for pydantic.BaseModel.
  • Python Dataclasses: Full support for classes decorated with @dataclasses.dataclass.
  • Generic Python Classes: Experimental support for converting plain Python classes that act as data containers (see Experimental Features).

Core Features

  • Automatic Django Model Generation: Scans your project to discover data classes and generates a complete, ready-to-use models.py file.
  • Bidirectional Data Mapping: The generated Django models, or models inheriting from the provided base classes, include methods like .from_pydantic() and .to_pydantic() for easy and reliable data conversion.
  • Relationship Management: Intelligently detects relationships between your source models and automatically creates the corresponding ForeignKey and ManyToManyField fields in Django.
  • Timescale-aware Generation (optional): Provides heuristics and safe wiring for TimescaleDB so hypertables never use illegal hypertable→hypertable FKs (replaced with indexed soft references), while preserving legal FK patterns.
  • Type Hint Aware: Leverages type hints to create the most appropriate Django model fields, including support for Optional, Union, Literal, and generic collections.
  • Extensible & Modular: The library is structured into distinct modules for pydantic, dataclass, and typedclass handling, allowing for clear separation of concerns. You can dive into the core logic in src/pydantic2django/core/.

Full Documentation

For the complete documentation site, visit the GitHub Pages deployment: pydantic2django docs.

Alternatives

Consider django-pydantic-field which has lots of cool features but not quite as much scope (and, commensurately, not as much complexity) as this library.

Installation

pip install django-typed2django

How It Works

Pydantic2Django operates using a three-stage pipeline:

  1. Discovery: It scans specified Python packages to find and identify source models (Pydantic, dataclass, etc.).
  2. Factory: For each discovered model, it analyzes its fields, type hints, and relationships to create an in-memory representation of a Django model.
  3. Generator: It uses the in-memory representation and Jinja2 templates to generate the final Python code for your models.py file, including all necessary imports, model classes, and field definitions.

Usage

Example 1: Generating a models.py File

The most common use case is to generate a Django models.py file from your existing Pydantic models or dataclasses.

Let's say you have Pydantic models in my_app/pydantic_models.py:

# my_app/pydantic_models.py
import uuid
from pydantic import BaseModel, Field

class User(BaseModel):
    id: uuid.UUID = Field(default_factory=uuid.uuid4)
    name: str
    email: str

class Product(BaseModel):
    id: uuid.UUID = Field(default_factory=uuid.uuid4)
    name: str
    price: float
    owner: User

You can generate the Django models with a simple script:

# scripts/generate_django_models.py
from typed2django.pydantic.generator import StaticPydanticModelGenerator

# Create a generator for Pydantic models
generator = StaticPydanticModelGenerator(
    output_path="my_app/models.py",
    packages=["my_app.pydantic_models"],
    app_label="my_app",
    verbose=True
)

# Generate the models file
generator.generate_models_file()
print("Django models generated successfully!")

This will create my_app/models.py containing User and Product Django models, complete with a ForeignKey relationship.

Note: For dataclasses, you would use DataclassDjangoModelGenerator from typed2django.dataclass.

Example 2: Using the Generated Models

The generated models inherit from a base class that provides helpful conversion methods.

# my_app/views.py
from my_app.models import User as DjangoUser
from my_app.pydantic_models import User as PydanticUser

# Assume you get a Pydantic object from an API call
pydantic_user = PydanticUser(name="Jane Doe", email="jane.doe@example.com")

# 1. Create a new Django model instance from the Pydantic object
django_user = DjangoUser.from_pydantic(pydantic_user)
django_user.save()

# 2. Retrieve a Django object and convert it back to a Pydantic object
retrieved_user = DjangoUser.objects.get(name="Jane Doe")
pydantic_version = retrieved_user.to_pydantic()

assert pydantic_version.name == "Jane Doe"

This bidirectional conversion makes it trivial to move data between your application logic and the database.

Advanced Usage

Filtering Models

You can provide a filter_function to the generator to selectively include or exclude models from the generation process.

def user_only_filter(model):
    """Only include models with names containing 'User'"""
    return "User" in model.__name__

generator = StaticPydanticModelGenerator(
    # ... other args
    filter_function=user_only_filter,
)

TimescaleDB Integration (Optional)

Pydantic2Django can help you generate models that follow TimescaleDB’s constraints and best practices.

  • Safe FK policy

    • Hypertable → Dimension: FK allowed.
    • Dimension → Dimension: FK allowed.
    • Hypertable → Hypertable: Not allowed by TimescaleDB. The generator replaces these with an indexed soft reference field (e.g., UUIDField(db_index=True, null=True, blank=True)), leaving referential checks to the application/background jobs.
  • Heuristics to classify hypertables vs dimensions (XML path)

    • Classified by signals like: presence of time/timestamp/sequence fields; unbounded list growth; event/observation-like names (e.g., Samples, Events, Condition); negative weight for definition/metadata types (e.g., *Definition*, *Parameters*, Header).
    • The XML generator chooses a per-model base:
      • Hypertable types use pydantic2django.django.timescale.bases.XmlTimescaleBase.
      • Dimension types use pydantic2django.django.models.Xml2DjangoBaseClass.
    • Illegal hypertable→hypertable relations are automatically converted to soft references.
  • Using Timescale bases in other paths

    • Pydantic and Dataclass paths can opt-in by setting the base explicitly before generation:
from pydantic import BaseModel
from pydantic2django.django.timescale.bases import PydanticTimescaleBase
from pydantic2django.pydantic.generator import StaticPydanticModelGenerator

class SampleObservation(BaseModel):
    device_id: str
    timestamp: int
    value: float

gen = StaticPydanticModelGenerator(output_path="models.py", packages=["my_pkg"], app_label="my_app")
# Force Timescale-enabled base for generated models (treat as hypertables)
gen.base_model_class = PydanticTimescaleBase
gen.generate_models_file()

For XML schemas, Timescale handling is automatic via heuristics. For non-XML paths, choose a Timescale base where appropriate.

Experimental Features

Generic Python Class Conversion

The library includes an experimental generator for converting plain Python classes into Django models, located in src/pydantic2django/typedclass/. This is useful for persisting configuration objects or instances of classes from third-party libraries.

Due to its experimental nature, it relies heavily on clear type hints in __init__ and may require manual adjustments to the generated code. You can read more about its goals and limitations in the TypedClass README.

Testing

Run the tests with:

uv run pytest -q

Contributing

Contributions are welcome! Please read the contributing guide: CONTRIBUTING.md.

  • All pull requests must pass the full test suite locally and in CI to demonstrate no regressions, or include a clear explanation for why automated tests are not appropriate for the change (with manual validation steps or rationale).
  • Aim to maintain backward compatibility, keep dependencies minimal, and follow PEP 8 with type hints.

License

MIT

Metadata

Release files for django-typed2django 1.0.20

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-typed2django 1.0.20
File Size Uploaded
django_typed2django-1.0.20.tar.gz 789.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-typed2django 1.0.20
File Interpreter ABI Platform
django_typed2django-1.0.20-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / django_typed2django-1.0.20.tar.gz

Download URL django_typed2django-1.0.20.tar.gz
Size 789.9 kB
Tags Source
SHA-256 checksum
How to use checksums
8882dfca9e986bf2297b765f43d3c02e1ef473010b33570c49c00a447268870b
BLAKE2b-256 checksum
How to use checksums
04d0a98d3df44f7e568edae87b5f37a98dc50ad6970a2a82a4c5fe6573c99526
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2025.

Transparency log

Release files / django_typed2django-1.0.20-py3-none-any.whl

Download URL django_typed2django-1.0.20-py3-none-any.whl
Size 210.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0dedbaf69baf59a1a89d09b2adb9b0bb08f05c1b0f77d02afe5ecab79597e1f1
BLAKE2b-256 checksum
How to use checksums
1bf2478641f4f054cbee4d3aeebe1bdc44753a875cd557bafb504ddae0e3dfa8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.20 This release

2 release files

1.0.19

2 release files

1.0.18

2 release files

1.0.17

2 release files

1.0.16

2 release files

1.0.15

2 release files

1.0.14

2 release files

1.0.12

2 release files

1.0.11

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page