Performance¶
Django Cast is built with performance as a core consideration, using advanced patterns and caching strategies to deliver content efficiently even under high load.
Architecture Overview¶
Repository Pattern¶
Django Cast uses a sophisticated repository pattern that sits between the database and Django’s ORM:
Database → Django ORM/Raw SQL → Repository → Dict → JSON Cache → Dict → Django Models → Template
This architecture enables:
Caching between database queries and model instantiation
Minimal database queries through aggressive prefetching
JSON-serialized cache storage for complex querysets
Key Components¶
PostQuerySnapshot Base Class: Foundation for all repositories
PostDetailContext: Optimized single post queries
BlogIndexContext: Efficient post list queries with filtering/pagination
FeedContext: Specialized for RSS/Atom generation
RenditionsForPost lookups: Image rendition management
Query Optimization¶
Prefetch Strategies¶
Repositories use aggressive prefetching to minimize queries:
# Bad: N+1 queries
for post in posts:
print(post.author.name) # Query per post
print(post.images.all()) # Query per post
# Good: prefetch once and reuse lookups
snapshot = PostQuerySnapshot.create_from_post_queryset(
request=request,
site=site,
queryset=posts,
)
# Snapshot contains prefetched media and renditions by post ID
Optimization Techniques¶
select_related: For one-to-many relationships
prefetch_related: For many-to-many relationships
only(): Load only required fields
defer(): Exclude expensive fields
Prefetch objects: Custom prefetch queries
Example implementation:
snapshot = PostQuerySnapshot.create_from_post_queryset(
request=request,
site=site,
queryset=blog.get_published_posts().select_related("owner", "cover_image"),
)
Caching Strategies¶
Multi-Level Caching¶
Django Cast implements caching at multiple levels:
Repository Cache
JSON-serialized query results
Filesystem-based storage
Automatic invalidation
Configurable timeout
Rendition Cache
Generated image sizes
AVIF and JPEG formats
Lazy generation
Persistent storage
Feed Cache
Complete RSS/Atom feeds
Reduces XML generation
Conditional GET support
Hourly refresh default
Cache Configuration¶
# Repository cache settings
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
'TIMEOUT': 3600, # 1 hour
}
}
# Built-in feed routes explicitly use a five-minute response cache.
# CAST_FEED_CACHE_TIMEOUT is not a supported setting.
# Image slot settings
CAST_REGULAR_IMAGE_SLOT_DIMENSIONS = [
(1110, 740),
]
CAST_GALLERY_IMAGE_SLOT_DIMENSIONS = [
(1110, 740),
(120, 80),
]
These settings define layout slots. django-cast derives multiple rendition
widths per slot for responsive srcset output. Gallery thumbnail renditions
also normalize embedded ICC profiles to compact sRGB by default, avoiding large
camera/display profiles in small thumbnails without changing uploaded originals
or gallery modal/full-size renditions.
Media Optimization¶
Image Handling¶
Responsive images with automatic optimization:
Format Selection: AVIF with JPEG fallback
Size Variants: Multiple renditions per breakpoint
Lazy Loading: Native browser lazy loading
Bulk Generation: Renditions created in batches
Example rendition generation:
# Automatic rendition creation
for width in [150, 300, 600, 900, 1200]:
image.get_rendition(f'width-{width}')
image.get_rendition(f'width-{width}|format-avif')
Audio File Optimization¶
Multiple format support (MP3, M4A, OGG, OPUS)
File size caching with admin action
Metadata extraction optimization
Progressive download support
Bulk Operations¶
Admin Actions¶
Performance-focused admin actions:
Cache File Sizes: Update all audio file sizes
Generate Renditions: Bulk create image renditions
Clear Caches: Selective cache invalidation
Rebuild Indexes: Search index optimization
Example admin action:
@admin.action(description="Cache file sizes")
def cache_file_sizes(modeladmin, request, queryset):
for audio in queryset:
audio.cache_audio_file_sizes()
Database Optimization¶
Index Strategy¶
Key database indexes for performance:
class Meta:
indexes = [
models.Index(fields=['date', 'blog']),
models.Index(fields=['is_published', 'date']),
models.Index(fields=['author', 'is_published']),
]
Query Reduction¶
Techniques to minimize database load:
Denormalized fields for common queries
Computed fields stored in database
Aggregate queries cached
Raw SQL for complex operations
Monitoring Performance¶
Debug Toolbar¶
Use Django Debug Toolbar to identify issues:
# Development settings
if DEBUG:
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
Performance Metrics¶
Track key metrics:
Query Count: Aim for < 10 queries per page
Query Time: Target < 100ms total
Cache Hit Rate: Should be > 80%
Page Load Time: Target < 1 second
Spam Filter Performance¶
The integrated spam filter is optimized for speed:
Pure Python implementation (100 lines)
Naive Bayes algorithm
In-memory classification
Performance metrics in admin: - Precision/Recall/F1 scores - Training time tracking - Real-time classification
Best Practices¶
Use Repositories: Always access data through repositories
Cache Aggressively: Cache expensive operations
Prefetch Related Data: Avoid N+1 queries
Monitor Query Count: Use debug toolbar in development
Optimize Images: Let the system handle renditions
Bulk Operations: Process multiple items together
Index Strategically: Add indexes for common queries
Common Performance Issues¶
High Query Count
Use repository pattern
Add prefetch_related calls
Check for missing select_related
Slow Image Loading
Enable rendition caching
Use lazy loading
Check rendition dimensions
Feed Generation Timeout
Configure an appropriate Django cache backend for the built-in feed cache
Measure full-archive feed size (there is no built-in item-limit setting)
Use FeedContext
Search Performance
Rebuild search indexes
Check database indexes