Django上具有相同模型的不同数据库

时间:2013-08-02 12:23:16

标签: python django django-queryset

我有以下问题:

我需要为每个用户(或一组用户)使用相同模型的不同数据库。我有办法找出用户与哪个数据库相关。问题是我总是必须在我做的每个查询中使用using方法。

例如:

Thing.objects.using('appropriate_database').all()

有没有办法避免使用using并以某种方式隐含用户/数据库关系?

3 个答案:

答案 0 :(得分:1)

听起来像一个糟糕的设计无法扩展到我。每次添加用户时都必须复制模式。

更好的设计会让表USER与每个用户所需的实体之间存在一对多和多对多的关系。

答案 1 :(得分:1)

我们做到了!让我解释一下。

我们编写了一个自定义中间件,并将其注册为settings.py文件中的中间件类。

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'our.custom.middleware.Class',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

此中间件具有process_request方法,该方法创建线程变量(from threading import local)以存储当前用户的相应数据库名称。由于每个请求都由不同的线程处理,我们知道我们的变量值不会被另一个线程意外更改。

下一步是创建一个Database Router并注册它。

DATABASE_ROUTERS = ('our.custom.database.Router',)

注意:默认settings.py没有DATABASE_ROUTERS变量。你必须创建它。

我们的自定义Routerdb_for_readdb_for_write具有相同的实现。这些方法唯一做的就是返回存储在我们的线程变量上的数据库名称。

就是这样。现在,每次我们需要恢复或保存模型对象时,我们都不必调用using

答案 2 :(得分:0)

您可以在模特上创建第二个经理:

class MyModelManager(models.Manager):
    def get_query_set(self):
        return super(MyModelManager, self).get_query_set().using('appropriate_database')

class MyModel(models.Model):
    # "objects" is the default manager
    objects_db2 = MyModelManager()

    field1 = models.CharField(...)

class MyModel2(models.Model):
    objects_db2 = MyModelManager()
    ...

然后使用查询MyModel.objects_db2.filter(...).order_by(...)...