69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
from django.conf import settings
|
|
from django.db import models
|
|
from django.core.cache import cache
|
|
|
|
class DatabaseRouter:
|
|
"""
|
|
A router to control database operations and optimize query routing
|
|
"""
|
|
|
|
def db_for_read(self, model, **hints):
|
|
"""
|
|
Route read operations to the appropriate database
|
|
"""
|
|
# Check if model has a cached query
|
|
cache_key = f"db_read_{model._meta.model_name}"
|
|
cached_db = cache.get(cache_key)
|
|
if cached_db:
|
|
return cached_db
|
|
|
|
# Default to primary database
|
|
return 'default'
|
|
|
|
def db_for_write(self, model, **hints):
|
|
"""
|
|
Route write operations to the appropriate database
|
|
"""
|
|
return 'default'
|
|
|
|
def allow_relation(self, obj1, obj2, **hints):
|
|
"""
|
|
Allow relations between objects
|
|
"""
|
|
return True
|
|
|
|
def allow_migrate(self, db, app_label, model_name=None, **hints):
|
|
"""
|
|
Allow migrations on the default database
|
|
"""
|
|
return db == 'default'
|
|
|
|
def optimize_query(self, queryset, **hints):
|
|
"""
|
|
Optimize the query based on model and hints
|
|
"""
|
|
# Add select_related for foreign key relationships
|
|
if hasattr(queryset.model, '_meta'):
|
|
related_fields = [
|
|
f.name for f in queryset.model._meta.get_fields()
|
|
if f.is_relation and not f.many_to_many
|
|
]
|
|
if related_fields:
|
|
queryset = queryset.select_related(*related_fields)
|
|
|
|
# Add prefetch_related for many-to-many relationships
|
|
m2m_fields = [
|
|
f.name for f in queryset.model._meta.get_fields()
|
|
if f.many_to_many
|
|
]
|
|
if m2m_fields:
|
|
queryset = queryset.prefetch_related(*m2m_fields)
|
|
|
|
# Add caching for frequently accessed queries
|
|
if hints.get('cache', True):
|
|
cache_key = f"query_{queryset.model._meta.model_name}_{hash(str(queryset.query))}"
|
|
cached_result = cache.get(cache_key)
|
|
if cached_result is not None:
|
|
return cached_result
|
|
|
|
return queryset |