Django多数据库路由

时间:2011-11-08 16:59:19

标签: python django

我一直在使用手动数据库选择来处理一个有两个单独dbs的项目。我在设置中定义了我的数据库。经过一些进一步的阅读后,似乎数据库路由实际上就是这样。但是,在阅读了这里的文档和相关帖子后,我比以往更加困惑。

在我的设置中,我有:

DATABASES = {
    'default': {
       .... 
    },
    'my_db2': {
       ....
    }
}

DATABASE_ROUTERS = ['myapp2.models.MyDB2Router',]

我知道我必须像我这样定义我的路由器类(我想想在myapp2.models.py中):

class MyDB2Router(object):
"""A router to control all database operations on models in
the myapp2 application"""

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

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

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

def allow_syncdb(self, db, model):

    if db == 'my_db2':
        return model._meta.app_label == 'myapp2'
    elif model._meta.app_label == 'myapp2':
        return False
    return None
那么什么?每个模型是否需要meta.app_label或者是自动的吗? 除此之外,我仍然会收到错误:

django.core.exceptions.ImproperlyConfigured:导入数据库路由器JournalRouter时出错:“无法导入名称连接

任何人都可以帮助我了解正在发生的事情和出了什么问题吗?任何帮助非常感谢。

4 个答案:

答案 0 :(得分:25)

好的,所以我解决了自己的问题。路由器类进入 / myapp2 下名为routers.py的单独文件。不需要 meta.app_label ,因为我猜它是自动分配的。希望这有助于某人。我还记录了流程here

答案 1 :(得分:6)

没帮我,所以我做了一些调试。也许结果可以为某人带来一些痛苦。 :) django 1.4中的问题是当django尝试导入自定义路由器类时发生的循环引用。
这发生在django.db.utils.ConnectionRouter中。在我的情况下,应用__init__.py导入了一个模块(确切地说tastypie.api),然后(通过长链)导入了django.db.models。这本身并不错,但是models尝试从connection导入django.db,而这恰好依赖于ConnectionRouter。这正是我们旅程开始的地方。因此错误。

这被描述为django中的一个错误< 1.6这里:https://code.djangoproject.com/ticket/20704并且有一个很好的小变更集应该在django 1.6中修复它:https://github.com/django/django/commit/6a6bb168be90594a18ab6d62c994889b7e745055

我的解决方案是将routers.py从app目录移动到项目目录。那里没有讨厌的依赖。

答案 2 :(得分:4)

省略的另一个错误是导入路由器中的模型,这将导致相同的错误,即使路由器是在不同的文件中定义的。

答案 3 :(得分:2)

如果您有一个使用多个数据库的应用程序,则可以基于每个应用程序和每个表进行路由。例如,如果您的应用程序是“控制台”并且您只希望“PoolServers”模型来自不同的后端,那么您可以将它放在您的routers.py中

class PoolServerRouter(object): 
def db_for_read(self, model, **hints):
    "Point only reads to poolserver  model to 'hamburger'"
    if model._meta.app_label == 'console' and model._meta.db_table == 'PoolServers':
        return 'hamburger'
    return 'default'