如何在多数据库项目中将管理员/身份验证用于迁移


这是

已知问题,迁移会忽略数据库路由。已知的解决方案是使用参数 --database 进行"手动"路由,并分别迁移每个应用程序。

但是,当使用 contrib 应用程序 admin/auth/内容类型时,应用迁移会触发post_migrate_signal,强制他们检查可能更改的模型的权限,并且他们尝试在用 --database 指定的 databasse 中执行此操作,而不是默认。

特别是,我有这样的设置:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'foo',
    'bar'
}
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR + '/var/db.sqlite'
    },
    'foo': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'HOST': 'foohost',
        'NAME': 'foo'
    },
    'bar': {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': '',
        'NAME': 'bar'
    }
}
DATABASE_ROUTERS = ['DumbDbRouter'] # simply returns app_label as  a target db

要运行 contrib 应用程序的初始迁移,请单独调用:

./manage.py migrate auth
./manage.py migrate admin
./manage.py migrate sessions

在此之后,将为每个找到的模型生成所有这些内容类型和权限。

现在,为我的应用运行迁移(初始或顺序):

./manage.py migrate foo --database=foo
# fails with error "Error creating new content types.". 

跟踪显示它是在尝试在数据库foo中查找表django_contenttypes引发的。现在,其他一些操作(如 runserver)将警告:"您有未应用的迁移。

我发现的唯一解决方法是禁用所有贡献内容(包括管理员 URL),然后进行迁移,然后将它们转回。

后果是不干净的。

您可以使用

路由器中的allow_migrate方法处理它。如果您的应用程序 fooapp 应该在数据库中,请确保内容类型应用程序也在那里。例如:

class DumbDbRouter(object)
    # ...
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if db == 'foo':
            return app_label in ['fooapp', 'contenttypes']  # <-- PAY ATTENTION
        elif app_label == 'fooapp':
            return False
        return None

在此处阅读文档。

  • 每个内容类型。内容类型,会话。会话和站点。站点可以存储在任何数据库中,只要有合适的路由器

希望对您有所帮助!

最新更新