无法使用数据库路由器使用save_model进行保存

Jav*_*ake 5 django django-models django-forms django-admin

我正在使用数据库路由器,因此我的应用程序有两个数据库.一个数据库用于默认的django数据,另一个数据库.

在我的管理员中,我已覆盖该save_model函数以保存created_by变量,但我无法执行此操作.

Cannot assign "<User: testuser>": the current database router prevents this relation.
Run Code Online (Sandbox Code Playgroud)

数据库路由:

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
Run Code Online (Sandbox Code Playgroud)

管理员:

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()
Run Code Online (Sandbox Code Playgroud)

我甚至试图通过使用来定义不同的数据库,save(using='thedb')但这也不起作用.我的数据库路由器错了吗?

MRH*_*ick 8

您遇到的问题源于存储在两个不同数据库中的对象之间存储关系的困难.在您的示例中,您声明已创建一个数据库来存储所有Django贡献对象,其中包括由auth应用程序创建的用户对象.同时,第二个模型的对象将存储在一个独立且完全独立的数据库中.当您尝试在存储在一个数据库中的新对象与User对象之间创建关系时,您正在尝试跨数据库关系.

跨数据库关系是一个难题,在Django中使用多个数据库时尚未解决.如果您想了解有关此问题的更多信息,Django文档会简要说明此问题(为清楚起见,请在下面复制).

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

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

如果您将Postgres,Oracle或MySQL与InnoDB一起使用,则会在数据库完整性级别强制执行 - 数据库级别的键约束会阻止创建无法验证的关系.

但是,如果您将SQLite或MySQL与MyISAM表一起使用,则不存在强制参照完整性; 因此,您可以"伪造"跨数据库外键.但是,Django并未正式支持此配置.

  • 这一切都有道理.所以我除了回到一个数据库之外别无选择. (2认同)

wmo*_*kal 7

如果您想坚持使用多个数据库(带有关系),您需要做的就是在您的路由器中实现一个 allow_relations 方法,该方法在您访问关系时返回 True 。