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

问题描述 投票:5回答:2

我正在使用数据库路由器,因此我的应用程序有两个数据库。一个数据库用于默认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

admin:

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')定义其他数据库,但这也不起作用。我的数据库路由器错了吗?

django django-models django-forms django-admin
2个回答
7
投票

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

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

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

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

如果您在InnoDB中使用Postgres,Oracle或MySQL,这是在数据库完整性级别上强制执行的-数据库级别的关键约束会阻止创建无法验证的关系。

但是,如果您将SQLite或MySQL与MyISAM表一起使用,则没有强制的参照完整性;结果,您可以“伪造”跨数据库外键。但是,Django并未正式支持此配置。


1
投票

[如果有人遇到这个问题,并希望坚持使用多个数据库(具有关联性,那么您要做的就是在路由器中实现allow_relations方法,当您访问该关联性时返回True)

© www.soinside.com 2019 - 2024. All rights reserved.