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:
- Dynamic Field Conversion (
Pydantic2DjangoBaseClass
) - 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.