【问题标题】:How to use DB router in Django 1.4如何在 Django 1.4 中使用数据库路由器
【发布时间】:2012-12-21 10:33:08
【问题描述】:

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

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

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 并定义一个数据库路由器,如下所示
(注意:根据SO帖子,如果您在models.py中定义了一个DB路由器,路由器将不起作用)

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。默认数据库没有那个表,但是当我使用inspectdb 生成模型时,'db1' 显然有它。作为证明,如果我在db1default 之间交换数据库配置,我可以毫无问题地访问该对象。

非常感谢任何帮助!

【问题讨论】:

    标签: python django multiple-databases


    【解决方案1】:

    我发现第 3 步“from django.db import connections ”中的语句阻止了 DB 路由器的注册。当我删除此语句时,路由器已注册,并且开始按预期工作。

    【讨论】:

      【解决方案2】:

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

      routers.py 中创建一个主路由器类,然后为每个数据库创建子类 - 并使用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 类覆盖。

      【讨论】:

      • 感谢您的回答!为什么在两者之间有一个子类可以解决问题呢?
      • DATABASE_ROUTERS 中需要两个类 - 每个 DB 一个。我是子类化,因为我更喜欢 DRY 代码(你可以重写为两个类,但代码几乎相同)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 2019-08-25
      • 1970-01-01
      • 2017-10-16
      • 2018-07-03
      • 1970-01-01
      • 2011-12-24
      相关资源
      最近更新 更多