【问题标题】:django: multiple db and contenttypedjango:多个数据库和内容类型
【发布时间】:2017-02-24 08:22:59
【问题描述】:

我正在使用一个名为“db_manager”的应用程序创建一个 Django 项目。我想创建两个数据库:一个用于 db_manager 模型,一个用于核心 django 模型(auth、admin、contentTypes、session...)

首先,我运行迁移以在 adw_core 数据库中创建核心模型。然后,我运行迁移以在 adw_facts db 中创建 db_manager 模型。我使用这个命令: python manage.py migrate db_manager --database adw_facts

我设置了一个路由器,将应用程序定向到适当的数据库:

settings.py

DATABASE_ROUTERS = ['data_warehouse.db_routers.DatabaseRouter']

MAP_APPS_TO_DB = {
    'db_manager': 'adw_facts',
    'django.contrib.auth': 'adw_core',
    'django.contrib.sessions': 'adw_core',
}

db_routers.py

class DatabaseRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label in settings.MAP_APPS_TO_DB:
            return settings.MAP_APPS_TO_DB[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in settings.MAP_APPS_TO_DB:
            return settings.MAP_APPS_TO_DB[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):
        # Allow any relation between apps that use the same database.
        db_obj1 = settings.MAP_APPS_TO_DB.get(obj1._meta.app_label)
        db_obj2 = settings.MAP_APPS_TO_DB.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            if db_obj1 == db_obj2:
                return True
            else:
                return False
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in settings.MAP_APPS_TO_DB:
            return db == settings.MAP_APPS_TO_DB[app_label]
        return None

当我运行迁移以在 adw_facts db 中创建 db_manager 模型时,我收到以下错误:

RuntimeError: Error creating new content types. Please make sure contenttypes is migrated before trying to migrate apps individually.

我确认表 'core_db.django_content_type' 存在。问题一定是django.contrib.contenttypes应用程序试图在adw_facts db中为db_manager创建contentTypes,但表core_db.django_content_type在adw_core db中。

我不想删除 contenttypes 应用,因为我将它与其他 Django 功能一起使用。

我可以想到以下解决方案:

  1. 禁用事实模型的内容类型

  2. 为 fact_db 创建一个 secnod 内容类型表

这些都不是很吸引人。如果您有更好的解决方案,请告诉我。

【问题讨论】:

  • 也许您有充分的理由进行这种分离,但如果您想将 userid 字段添加到您的模型之一或利用用户权限,则会出现问题,因为 Django 目前不支持 cross数据库连接。
  • 是的,我开始觉得这不是正确的方法,因为 Django 不太支持这个特性。文档中应该有警告。
  • @Nico - 在当前的 Django 文档中有一个关于 limitations of multiple databases 的警告。不知道有多久了。
  • 我也面临同样的问题。我想在另一个数据库中创建一个模型,不打算与主数据库中的其他模型建立任何关系,但是,ContentType 关系是强制性的,克服这个问题是我还没有找到解决方案。

标签: django


【解决方案1】:

刚遇到同样的问题(在 django 2.1 上)。 根据@Tony 提到的文档,您似乎需要从每个数据库中的几个 django 组件中复制数据。 这对我有用:

def allow_migrate(self, db, app_label, model_name=None, **hints):
    if app_label in ('sites', 'contenttypes', 'auth'):
        return True

    if app_label in settings.MAP_APPS_TO_DB:
        return db == settings.MAP_APPS_TO_DB[app_label]
    return None

【讨论】:

  • 感谢您提供解决方案。我现在离问题太远了,无法确认这是否解决了我遇到的问题。如果其他人确认这有帮助,我很乐意将其标记为正确答案。
  • 我可以确认将条件添加到路由器的allow_migrate 方法中,如上所示,将始终返回sitescontenttypesauthTrue 用于解决此问题给我的问题。
猜你喜欢
  • 2011-03-12
  • 2013-04-25
  • 1970-01-01
  • 2013-09-04
  • 2014-09-17
  • 1970-01-01
  • 2010-12-24
  • 2010-11-18
  • 1970-01-01
相关资源
最近更新 更多