如何使用给定的数据库在django中的方法中进行查询?

时间:2018-06-08 16:40:22

标签: python django database django-models decorator

情况就是这样。方法或函数具有几个数据库查询。有两个数据库,例如DATABASE_ADATABASE_B

def method():
    # database queries here
    orders = Order.objects.filter(...)
    products = Product.objects.filter(...)

如何使用decoratorany other ways轻松实现以下目标?任何人都可以提供example吗? model.objects.using(some database)是一种已知方法,但该方法中存在大量查询。我不想触摸它们,所以这不是一个选择。

# Here call method() using DATABASE_A
# here call method() using DATABASE_B

2 个答案:

答案 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。更新设置

以下是DATABASESsettings.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()