我正在使用数据库路由器,因此我的应用程序有两个数据库。一个用于默认django数据的数据库,另一个用于数据库。
在我的管理员中,我已覆盖save_model
函数以保存created_by
变量,但我无法执行此操作。
Cannot assign "<User: testuser>": the current database router prevents this relation.
数据库路由器:
from django.conf import settings
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
"""Point all read operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
"""Point all write operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[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.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
db_obj2 = settings.DATABASE_APPS_MAPPING.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_syncdb(self, db, model):
"""Make sure that apps only appear in the related database."""
if model._meta.app_label in ['south']:
return True;
elif db in settings.DATABASE_APPS_MAPPING.values():
return settings.DATABASE_APPS_MAPPING.get(model._meta.app_label) == db
elif settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return False
return None
管理员:
class SomeEntityAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
user = request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
if not obj.created_by:
obj.created_by = user
obj.save()
我甚至尝试使用save(using='thedb')
来定义不同的数据库,但这也不起作用。我的数据库路由器错了吗?
答案 0 :(得分:6)
您遇到的问题源于存储在两个不同数据库中的对象之间存储关系的困难。在您的示例中,您声明已创建一个数据库来存储所有Django贡献对象,其中包括由auth应用程序创建的用户对象。同时,第二个模型的对象将存储在一个独立且完全独立的数据库中。当您尝试在存储在一个数据库中的新对象与User对象之间创建关系时,您正在尝试跨数据库关系。
跨数据库关系是一个难题,在Django中使用多个数据库时尚未解决。如果您想了解有关此问题的更多信息,请the Django documentation has a brief note about this problem(为清晰起见,请在下方复制)。
Django目前不支持跨越多个数据库的外键或多对多关系。如果您已使用路由器将模型分区到不同的数据库,则由这些模型定义的任何外键和多对多关系必须位于单个数据库的内部。
这是因为参照完整性。为了维护两个对象之间的关系,Django需要知道相关对象的主键是有效的。如果主键存储在单独的数据库中,则无法轻松评估主键的有效性。
如果您将Postgres,Oracle或MySQL与InnoDB一起使用,则会在数据库完整性级别强制执行 - 数据库级别的键约束会阻止创建无法验证的关系。
但是,如果您将SQLite或MySQL与MyISAM表一起使用,则不存在强制参照完整性;因此,您可以“伪造”跨数据库外键。但是,Django并未正式支持此配置。
答案 1 :(得分:2)
如果有人遇到这个问题,并且想坚持使用多个数据库(具有关联),您要做的就是在路由器中实现allow_relations方法,当您访问该关系时,该方法将返回True