3

我有以下问题:

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

例如:

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

有没有办法避免使用using和隐含用户/数据库关系?

4

3 回答 3

1

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

更好的设计应该有一个表 USER 与每个用户所需的实体具有一对多和多对多关系。

于 2013-08-02T12:26:30.817 回答
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_ROUTERS = ('our.custom.database.Router',)

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

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

而已。现在我们不必在using每次需要恢复或保存模型对象时调用。

于 2013-08-07T14:09:49.800 回答
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(...)...

于 2013-08-02T12:32:33.260 回答