Provider backend pattern
Provider/backends pattern¶
This document explains the common pattern shared by the provider backends in src/pydantic2django/:
dataclass/pydantic/typedclass/xmlschema/
These backends implement the same high-level pipeline and reuse the core abstractions in src/pydantic2django/core/.
The shared pipeline¶
1) Discovery (find source models)
- Each backend provides a Discovery that subclasses core.discovery.BaseDiscovery[TModel].
- It scans the provided packages or inputs, applies default and user filters, and builds a dependency graph.
2) Factory (turn fields into Django Fields, then a model)
- Each backend provides a FieldFactory and a ModelFactory that subclass core.factories.BaseFieldFactory and BaseModelFactory.
- Field factories translate a single source field to a Django field and kwargs.
- Model factories iterate fields, handle collisions, build a Meta class, assemble the Django Model type, and construct optional context.
3) Generator (orchestrate and render)
- Each backend provides a ...ModelGenerator that subclasses core.base_generator.BaseStaticGenerator.
- It calls discovery, invokes the model factory for each source model to produce carriers, renders Jinja templates (django/templates/*.j2), and writes the output models.py.
Core building blocks reused by all backends¶
BaseDiscovery: common scanning/filtering hooks and dependency analysis entrypoints.BaseModelFactory/BaseFieldFactory: single-field conversion and whole-model assembly with aConversionCarrierfor state.BidirectionalTypeMapper+mapping_units: type mapping for Pydantic/Dataclass fields to Django fields, including enums, collections, and relationships.RelationshipConversionAccessor: resolves and tracks mappings between source models and generated Django models, used by mappers/factories.ImportHandler: collects and de-duplicates imports across definitions and context classes.ModelContext/ContextClassGenerator: holds non-serializable context and renders companion context classes (primarily for Pydantic).TypeHandler: normalizes types (Optional/List/Union/Annotated), produces readable type strings, and calculates required imports.
Backend specifics¶
Pydantic (pydantic/)¶
- Discovery:
PydanticDiscoveryfindsBaseModelclasses and builds a dependency graph from field annotations. - Factories:
PydanticFieldFactory+PydanticModelFactoryuseBidirectionalTypeMapperto convertFieldInfoto Django fields (includes union/multi-FK handling, relationships, enums/choices, defaults). - Generator:
StaticPydanticModelGeneratororchestrates generation and also renders per-model context classes where needed.
Dataclass (dataclass/)¶
- Discovery:
DataclassDiscoveryidentifies Python dataclasses and derives dependencies from dataclass field annotations. - Factories:
DataclassFieldFactory+DataclassModelFactoryuse the same bidirectional mapper; default/metadata resolution is tailored to dataclasses. - Generator:
DataclassDjangoModelGeneratorfollows the shared flow; context classes are typically not emitted.
TypedClass (typedclass/)¶
- Discovery:
TypedClassDiscoverytargets plain Python classes (not Pydantic/dataclasses), leveraging__init__parameters and class annotations for fields/deps. - Factories:
TypedClassFieldFactory+TypedClassModelFactorytranslate type hints using a type translator suited to generic classes. - Generator:
TypedClassDjangoModelGeneratorreuses the shared pipeline; focuses on simple type-hint based field generation.
XML Schema (xmlschema/)¶
- Discovery:
XmlSchemaDiscoveryparses XSDs viaXmlSchemaParser, gathers complex types, applies filters, and computes inter-type dependencies. - Factories:
XmlSchemaFieldFactory+XmlSchemaModelFactorymap XSD simple/complex types to Django fields. Handles enumerations (TextChoices), nillability/occurrence constraints, and post-pass injection of relationships (e.g., child FKs) viafinalize_relationships. - Generator:
XmlSchemaDjangoModelGeneratorextends the shared generator logic, callingfinalize_relationshipsbefore rendering and passing enum/context info to templates.
Relationship handling¶
- Pydantic/Dataclass:
BidirectionalTypeMapperinspects type hints and usesRelationshipConversionAccessorto resolve related model references (FK, O2O, M2M). It detects lists of known models for M2M and unions of models for multi-FK patterns. - XML Schema: relationships are derived from
key/keyref, element nesting, and configuration (fk/json/m2m). Some relations are injected after all models exist.
Imports and templates¶
ImportHandleraccumulates typing/pydantic/context and model imports during field conversion and context rendering, then de-duplicates for the templates.- All generators render with the shared Jinja templates in
src/pydantic2django/django/templates/(model_definition.py.j2,models_file.py.j2,context_class.py.j2,imports_block.py.j2).
Adding a new backend¶
- Implement a
Discoverysubclass to find your source models and compute dependencies. - Implement a
FieldFactory+ModelFactorypairing to convert fields and assemble models. - Implement a
...ModelGeneratorsubclass ofBaseStaticGeneratorand wire your discovery/factory and any special context/relationship steps. - Reuse
BidirectionalTypeMapperwhere possible; add newTypeMappingUnits if your source introduces new type shapes. - Leverage
ImportHandler,RelationshipConversionAccessor, andTypeHandlerto keep logic consistent and DRY.
API reference¶
For full, up-to-date API details of these modules and classes, see the generated reference: API Reference.