我遇到了Django模型数据库路由问题。我已经做了相当多的研究,但是没有运气。
首先,了解与该问题相关的应用程序的信息。
我选择使用数据库路由来分离应用程序中的模型。该应用程序适用于n个公司(例如foo1),并且它们都有自己的django应用程序,包括几乎相同的models.py文件。
模式路由由用户在db连接中完成。
-“默认”数据库连接的目的是处理auth和contenttype随附的模型。这是与foo0相同的架构,因为此连接适用于处理django auth AbstractUser扩展的应用程序。
我的settings.py看起来像这样。
DATABASE_ROUTERS = ['django_project.database_router.django_projectDatabaseRouter']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER' : 'foo0_user@django_projectdatabase',
'PASSWORD' : 'x',
'HOST' : 'x',
'PORT' : '5432',
},
'foo0': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER' : 'foo0_user@django_projectdatabase',
'PASSWORD' : 'x',
'HOST' : 'x',
'PORT' : '5432',
},
'foo1':{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER' : 'foo1_user@django_projectdatabase',
'PASSWORD' : 'x',
'HOST' : 'x',
'PORT' : '5432',
},
'foo2':{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER' : 'foo2_user@django_projectdatabase',
'PASSWORD' : 'x',
'HOST' : 'x',
'PORT' : '5432',
}
}
这是相应的数据库路由器类(出于调试目的进行了调整)。
class django_projectDatabaseRouter:
def db_for_read(self, model, **hints):
print('reading from database ' + model._meta.app_label)
return model._meta.app_label
def db_for_write(self, model, **hints):
print('writing to database ' + model._meta.app_label)
return model._meta.app_label
def allow_relation(self, obj1, obj2, **hints):
#if obj1._meta.app_label == obj2._meta.app_label:
# return True
#elif obj1._meta.app_label in ['auth','contenttypes','sessions'] or obj1._meta.app_label in ['auth','contenttypes','sessions']:
# return True
#return None
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'foo0':
print(app_label + ', ' + str(db=='foo0'))
return db == 'foo0'
elif app_label == 'foo1':
print(app_label + ', DB=' + db + ', model='+model_name)
db='foo1'
return db == 'foo1'
elif app_label == 'foo2':
print('app_label='app_label + ', ' + str(db=='foo2'))
return db == 'foo2'
elif app_label in ['auth','contenttypes','sessions'] and db == 'default':
print('--------auth---------')
print(db + ', ' + app_label + ', ' + model_name)
return db=='default'
return db == app_label
foo0模型都具有相应的数据库名称
class Field_Picture(models.Model):
field1_id = models.ForeignKey(Field, on_delete=models.SET_NULL, null=True)
picture_id = models.ForeignKey(Picture, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
class Meta:
app_label = 'foo1'
运行 python manage.py makemigrations 创建正确的迁移,但是当我运行 manage.py migration foo1 0001 我得到了这个输出。
Running migrations:
Applying foo1.0001_initial...
app_label=foo1, DB=default, model=some_random_model
app_label=foo1, DB=default, model=some_random_model
....
OK
如您所见,模型已链接到“默认”数据库,而不是所需的“ foo1”。我认为问题出在以下事实:路由器从未在auth以外的模型上调用db_for_write函数。
总结我的问题:
数据库路由器将忽略模型元数据的app_label,仅通过allow_migrate()函数传递db ='default'的迁移。
如果有人遇到类似问题或对该领域有知识,我将不胜感激。