【问题标题】:Unable to save with save_model using database router无法使用数据库路由器使用 save_model 保存
【发布时间】:2014-12-22 03:21:26
【问题描述】:

我正在使用数据库路由器,因此我的应用程序有两个数据库。一个数据库用于默认 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') 定义不同的数据库,但这也不起作用。我的数据库路由器有问题吗?

【问题讨论】:

    标签: django django-models django-forms django-admin


    【解决方案1】:

    您遇到的问题源于难以存储存储在两个不同数据库中的对象之间的关系。在您的示例中,您声明您已经创建了一个数据库来存储所有 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 并未正式支持此配置。

    【讨论】:

    • 这一切都说得通。所以我显然别无选择,只能回退到一个数据库。
    • 优秀的评论。我发现关于这些问题的信息太少了。但我不想退缩。 @JavaCake,那之后你有什么好运吗?
    【解决方案2】:

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

    【讨论】:

    • 我在 django 项目中添加了一个额外的数据库。当我运行 python3 manage.py migrate --datebase=dbname 时,我遇到了这个问题。并在我的路由器文件的 allow_relations 方法中返回 ture 解决了这个问题。谢谢
    猜你喜欢
    • 2023-03-17
    • 2015-02-07
    • 2020-07-29
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多