情况就是这样。方法或函数具有几个数据库查询。有两个数据库,例如DATABASE_A
和DATABASE_B
。
def method():
# database queries here
orders = Order.objects.filter(...)
products = Product.objects.filter(...)
如何使用decorator
或any other ways
轻松实现以下目标?任何人都可以提供example
吗? model.objects.using(some database)
是一种已知方法,但该方法中存在大量查询。我不想触摸它们,所以这不是一个选择。
# Here call method() using DATABASE_A
# here call method() using DATABASE_B
答案 0 :(得分:1)
正如Multiple databases docs中指定的那样:
您可以在任何位置为QuerySet选择数据库 QuerySet“chain。”只需在QuerySet上调用using()即可获得另一个 使用指定数据库的QuerySet。
>>> # This will run on the 'default' database.
>>> Author.objects.all()
>>> # So will this.
>>> Author.objects.using('default').all()
>>> # This will run on the 'other' database.
>>> Author.objects.using('other').all()
答案 1 :(得分:0)
Django, Databases, and Decorators有一个解决方案 django DATABASE_ROUTERS
Here您可以从docs.djangoproject.com找到示例。以下是来自Django,数据库和装饰者的摘要':
<强> 1。编写自定义装饰器
此处将decorator
命名为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。更新设置
以下是DATABASES
中settings.py
的示例:
DATABASES = {
'default': {
...
},
'read-only': {
...
}
}
DATABASE_ROUTERS = ['decorators.AnalyticsRouter']
第3。以下是如何使用
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()