Django admin save_model 没有在 Postgres 中推进主键

Posted

技术标签:

【中文标题】Django admin save_model 没有在 Postgres 中推进主键【英文标题】:Django admin save_model not advancing primary key in Postgres 【发布时间】:2020-02-18 08:58:00 【问题描述】:

所以我在 Django 管理员中有一个函数允许我在数据库中创建一个重复的MyModel

def save_model(self, request, obj, form, change):
    if '_saveasnew' in request.POST:
        old_obj_id = resolve(request.path).args[0]
        old_obj = MyModel.objects.get(id=old_obj_id)
        obj.other_id = old_obj.other_id
        obj.status = old_obj.status
        obj.project_id = old_obj.project_id
        obj.test_url = old_obj.test_url
        obj.save()
    super(MyModelAdmin, self).save_model(request, obj, form, change)

这个创建工作正常,但是我有另一个系统与这个数据库交互,每次调用这个函数时都会看到插入失败。例如,如果我以这种方式在 Django admin 中创建 2 个重复条目,那么另一个系统将看到两个错误,例如

IntegrityError 重复键值违反唯一约束“my_model_pkey”详细信息:键 (id)=(1234) 已存在。

我正在使用 Django 1.11.15 和 PostgreSQL 9.5.15。

【问题讨论】:

你运行的是什么版本的 Django?请注意,随着版本号的增加,Django 放弃了对旧 PostgreSQL 版本的支持。请参阅docs.djangoproject.com/en/2.1/releases/2.1/… 或任何其他相关版本。 @GjertG 添加了使用的版本。 两个应用程序是否使用相同的版本?我假设“另一个系统”是指一个单独的 Django 应用程序?我的猜测是在指向正确的对象方面存在问题。 传递给函数的参数到底是什么?对 obj 参数最感兴趣。 本例中的“其他系统”只是直接的SQL插入语句。 save_model 函数是 Django ModelAdmin 类中的一个被覆盖的函数 (docs) 【参考方案1】:

我最好的猜测是,您的代码在某处告诉您的数据库创建一个新的对象行并将该行的 ID 显式设置为 X。实际上,代码应该告诉您的数据库创建一个新的对象行并隐式地将该行的 ID 设置为下一个可用整数。

您的代码令人困惑,因为您正在以非常复杂的方式进行操作。为什么这个函数同时接受一个对象和一个请求?然后它从请求中找到旧对象?新对象是在哪里创建的?

一种更简单的方法是首先检查您是否要另存为新的。如果没有,请使用更新对象并为其提供现有对象的功能。如果是另存为新请求,则创建一个与现有对象具有相似值的新对象行(ID 除外)。然后使用更改更新该新对象。或者你的逻辑应该有效。无论如何,如果您考虑一下步骤的顺序,有一种更直接的方法可以完成您希望发生的步骤。

【讨论】:

您能否编写而不是描述您的“更简单方式”的代码?

以上是关于Django admin save_model 没有在 Postgres 中推进主键的主要内容,如果未能解决你的问题,请参考以下文章

Django admin save_model 没有在 Postgres 中推进主键

覆盖 Django InlineModelAdmin 上的 save_model

为啥 save_model 方法在 admin.StackedInline 中不起作用?

在 django 中测试 admin.ModelAdmin

Django Admin Cookbook-40如何为Django Admin覆盖保存操作

Django Admin Cookbook-24如何从两个不同的模型创建一个Django Admin后台页面