Skip to content

Pydantic to Django Storage Approaches

This document compares two different approaches for storing Pydantic models in Django: Dynamic Field Conversion vs Direct Serialization.

Overview of Approaches

The library provides two distinct mechanisms for storing Pydantic models in Django:

  1. Dynamic Field Conversion (Pydantic2DjangoBaseClass)
  2. Direct Serialization (Pydantic2DjangoStorePydanticObject)

Core Approach Differences

Dynamic Field Conversion

  • Field Mapping: Creates individual Django model fields for each Pydantic field
  • Database Schema: Maintains a structured database schema matching the Pydantic model
  • Relationship Handling: Proper foreign key relationships in the database
  • Query Support: Full Django ORM query capabilities on individual fields

Direct Serialization

  • JSON Storage: Stores entire Pydantic object as JSON in a single field
  • Schema Flexibility: No need to modify database schema for model changes
  • Simplicity: Simpler codebase with less conversion logic
  • Document Style: Better suited for document-style data storage

Technical Implementation Differences

Storage Structure

  • Dynamic Field Conversion:
  • Each Pydantic field becomes a database column
  • Proper database types for each field
  • Support for indexes and constraints
  • Native database relationships

  • Direct Serialization:

  • Single JSON field contains all data
  • No individual field columns
  • No direct database relationships
  • Flexible schema evolution

Query Capabilities

  • Dynamic Field Conversion:

    # Can query on specific fields
    MyModel.objects.filter(specific_field="value")
    MyModel.objects.exclude(number_field__gt=100)
    MyModel.objects.values('specific_field')
    

  • Direct Serialization:

    # Must query on JSON field
    MyModel.objects.filter(data__contains={"field": "value"})
    # Must load entire object to access specific fields
    instance = MyModel.objects.get(id=1)
    pydantic_obj = instance.to_pydantic()
    

Advantages and Disadvantages

Dynamic Field Conversion

Advantages

  • Better query performance on specific fields
  • Proper database-level relationships
  • Full Django ORM capabilities
  • Database-level constraints and validation
  • Better support for complex queries and joins
  • Field-level indexing
  • Efficient partial data retrieval

Disadvantages

  • More complex implementation
  • Requires database migrations for model changes
  • More code to maintain
  • Higher initial development overhead
  • More complex relationship handling

Direct Serialization

Advantages

  • Simpler implementation
  • No database migrations needed for model changes
  • Easier to maintain
  • Better for rapidly evolving schemas
  • Simpler relationship handling
  • More flexible data structure
  • Faster development iteration

Disadvantages

  • Limited query capabilities
  • Must load entire object to access fields
  • No database-level relationships
  • Less efficient for partial data access
  • Limited database-level validation
  • No field-level indexing

Use Case Recommendations

Use Dynamic Field Conversion When:

  • You need efficient querying on specific fields
  • You have complex relationships that benefit from proper foreign keys
  • You need database-level constraints
  • Performance of field-specific queries is important
  • You're integrating heavily with other Django models
  • You need aggregation and complex filtering
  • Your schema is relatively stable

Use Direct Serialization When:

  • Your models change frequently
  • You don't need to query specific fields often
  • You're dealing with document-style data
  • You want simpler code maintenance
  • You don't need database-level relationships
  • You prioritize development speed over query performance
  • You need maximum schema flexibility

Code Examples

Dynamic Field Conversion

from pydantic import BaseModel
from pydantic2django import Pydantic2DjangoBaseClass

class MyPydanticModel(BaseModel):
    name: str
    age: int
    email: str

class MyDjangoModel(Pydantic2DjangoBaseClass[MyPydanticModel]):
    class Meta:
        app_label = 'myapp'

# Efficient field-specific queries
young_users = MyDjangoModel.objects.filter(age__lt=25)
email_list = MyDjangoModel.objects.values_list('email', flat=True)

Direct Serialization

from pydantic2django import Pydantic2DjangoStorePydanticObject

class MyDjangoModel(Pydantic2DjangoStorePydanticObject):
    class Meta:
        app_label = 'myapp'

# Store entire object
instance = MyDjangoModel.from_pydantic(pydantic_obj)
instance.save()

# Must load entire object to access fields
loaded = MyDjangoModel.objects.get(id=1)
pydantic_obj = loaded.to_pydantic()

Performance Implications

Query Performance

  • Dynamic Field Conversion: Better performance for field-specific queries
  • Direct Serialization: Better performance for whole-object operations

Storage Efficiency

  • Dynamic Field Conversion: More efficient for partial data access
  • Direct Serialization: More efficient for whole-object storage

Memory Usage

  • Dynamic Field Conversion: More efficient when accessing specific fields
  • Direct Serialization: Must load entire object into memory

Conclusion

The choice between these approaches depends on your specific requirements:

  • Choose Dynamic Field Conversion if you need:
  • Efficient field-specific queries
  • Database-level relationships
  • Complex filtering and aggregation
  • Integration with Django's ORM

  • Choose Direct Serialization if you need:

  • Schema flexibility
  • Simpler maintenance
  • Faster development iteration
  • Document-style storage

In practice, you might use both approaches in different parts of your application based on specific needs. The library's design allows for this flexibility by providing both implementations.