已知问题,迁移会忽略数据库路由。已知的解决方案是使用参数 --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
在此处阅读文档。
- 每个内容类型。内容类型,会话。会话和站点。站点可以存储在任何数据库中,只要有合适的路由器。
希望对您有所帮助!