4

我一直在尝试将 Django 1.4.3 设置为使用多个数据库,但对于我的生活,我无法让它工作。我阅读了关于 SO 的文档和帖子,并执行了以下操作:

1)在 中添加第二个 DB 配置settings.py,如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': '/tmp/django.db',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    },
    'db1' : {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db1',
        'USER': 'fake',
        'PASSWORD': 'fake',
        'HOST': 'fake.host.com',
        'PORT': '3306',
    },
}

2)创建一个routers.py并定义一个DB路由器如下
(注意:根据SO帖子,如果您在中定义一个DB路由器models.py,路由器将不起作用)

class DBRouter(object):
    def db_for_read(self, model, **hints):
        return 'db1'

    def db_for_write(self, model, **hints):
        return 'db1'

    def allow_syncdb(self, db, model):
        return 'db1'

3)将以下行添加到settings.py
(注意:根据SO帖子,这些行必须在DATABASES配置之后

from django.db import connections
DATABASE_ROUTERS = ['fakeproject.routers.DBRouter',]

这是错误的。不要放在from django.db import connections这里,因为它会阻止路由器注册

我的症状:
显然,我所有的呼叫都是通过默认数据库路由的。详情如下:

  • 两种数据库设置都有效(我可以manage.py indpectdb --database db1成功 执行

  • DATABASE_ROUTERS设置不会产生任何抱怨(即使我将错误的路径放入 DB 路由器,甚至是非字符串对象)

  • 当我尝试通过 访问我的对象时manage.py shell,我可以这样做,MyModel.objects.all()但是当我实际尝试迭代它时,我被告知no such table. 默认数据库没有那个表,但是当我使用它生成模型时,'db1' 显然有inspectdb它。作为证明,如果我在db1和之间交换数据库配置default,我可以毫无问题地访问该对象。

任何帮助都非常感谢!

4

2 回答 2

3

I found out that the statement in step 3 "from django.db import connections " was preventing the DB router to be registered. When I removed this statement, the router was registered and stuff started to work as expected.

于 2012-12-21T22:59:45.783 回答
1

我认为问题可能出现了,因为你routers.py只返回一个引用,'db1'但正如你所说,你只是被路由到'default'我不确定(我希望它是唯一路由到'db1'.

routers.py创建一个主路由器类,然后为每个 DB 子类化 - 并使用app_label字符串初始化,以便您可以将它们分开。

class MasterRouter(object):
    def __init__(self, app_label):
        super(MasterRouter, self).__init__()
        self.app_label = app_label

    def db_for_read(self, model, **hints):
        if model._meta.app_label == self.app_label:
            return self.app_label
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == self.app_label:
            return self.app_label
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == self.app_label or obj2._meta.app_label == self.app_label:
            return True
        return None

    def allow_syncdb(self, db, model):
        if db == 'default':
            return model._meta.app_label == self.app_label
        elif model._meta.app_label == self.app_label:
            return False
        return None

class DefaultRouter(MasterRouter):
    def __init__(self):
        super(DefaultRouter, self).__init__('default')

class DB1Router(MasterRouter):
    def __init__(self):
        super(DB1Router, self).__init__('db1')

然后在你settings.py声明路由器

DATABASE_ROUTERS = [ 'routers.DefaultRouter', 'routers.DB1Router' ]

当然,您可能希望以MasterRouter不同的方式设置类覆盖。

于 2012-12-21T13:43:24.923 回答