Django, Databases, and Decorators has a solution using
django DATABASE_ROUTERS.
Here you can find an example from docs.djangoproject.com. The follows is the summary from 'Django, Databases, and Decorators':
1. Writing a custom decorator
Here name the decorator as decorators.py:
from functools import wraps
try:
from threading import local
except ImportError:
from _threading_local import local
threadlocal = local()
class use_db_for_reads(object):
def __init__(self, database_name):
self.database_name = database_name
def __enter__(self):
setattr(threadlocal, 'DB_FOR_READ_ONLY', self.database_name)
def __exit__(self, exc_type, exc_value, traceback):
setattr(threadlocal, 'DB_FOR_READ_ONLY', None)
def __call__(self, test_func):
@wraps(test_func)
def inner(*args, **kwargs):
return test_func(*args, **kwargs)
return inner
def get_thread_local(attr, default=None):
return getattr(threadlocal, attr, default)
class AnalyticsRouter(object):
def db_for_read(self, model, **hints):
return get_thread_local('DB_FOR_READ_ONLY', 'default')
def db_for_write(self, model, **hints):
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return True
2. update settings
Here is an example of DATABASES in settings.py:
DATABASES = {
'default': {
...
},
'read-only': {
...
}
}
DATABASE_ROUTERS = ['decorators.AnalyticsRouter']
3. Here is how to use it
from decorators import use_db_for_reads
# Here call method() using DATABASE_A
with use_db_for_reads(DATABASE_A):
method()
# here call method() using DATABASE_B
with use_db_for_reads(DATABASE_B):
method()