2014-10-26 129 views
4

我正在使用数据库路由器,因此我有两个数据库用于我的应用程序。一个数据库用于默认的django数据,另一个用于数据库。无法使用数据库路由器save_model保存

在我的管理员,我已经覆盖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')定义不同的数据库,但不工作的。我的数据库路由器错了吗?

回答

5

您遇到的问题来自存储在两个不同数据库中的对象之间存储关系的困难。在你的例子中,你表示你已经创建了一个数据库来存储所有的Django贡献对象,其中包括由auth应用创建的User对象。同时,第二个模型的对象将被存储在一个完全独立的独立数据库中。当您尝试创建存储在一个数据库中的新对象与User对象之间的关系时,您正在尝试跨数据库关系。

跨数据库关系是一个难题,在Django中使用多个数据库时尚未解决。如果您想了解关于此问题的更多信息,请参阅the Django documentation has a brief note about this problem(为清晰起见,请在下面复制)。

Django目前不支持跨越多个数据库的外键或多对多关系。如果您使用路由器将模型分区到不同的数据库,则由这些模型定义的任何外键和多对多关系必须位于单个数据库内部。

这是因为参照完整性。为了维护两个对象之间的关系,Django需要知道相关对象的主键是有效的。如果主键存储在单独的数据库中,则无法轻松评估主键的有效性。

如果您将Postgres,Oracle或MySQL与InnoDB一起使用,这将在数据库完整性级别执行 - 数据库级别的关键约束会阻止创建无法验证的关系。但是,如果您在MyISAM表中使用SQLite或MySQL,则不存在强制的参照完整性;因此,您可能能够“伪造”跨数据库外键。但是,这种配置并未得到Django的正式支持。

+1

这一切都有道理。所以我显然没有别的选择,只能回到一个数据库。 – JavaCake 2014-10-27 07:40:17

+0

优秀评论。我发现有关这些问题的信息太少。但我不想倒退。 @JavaCake,之后你有幸运吗? – 2016-10-13 21:12:33