简体   繁体   English

Django save()运行INSERT而不是UPDATE:为什么?

[英]Django save() runs INSERT instead of UPDATE: Why?

Consider the following Django model: 考虑以下Django模型:

class Outlet(models.Model):
    a = models.CharField(max_length=253, primary_key=True, db_index=True)
    def _split(self, idx):
        if not self.a:
            return None
        return self.a.split(".")[idx]
    @property
    def b(self):
        return self._split(0)
    @property
    def c(self):
        return self._split(1)

Couple with this class registered in admin: 加上在admin中注册的此类:

@admin.register(Outlet)
class OutletAdmin(admin.ModelAdmin):
    fields = ("a", "b", "c")
    readonly_fields = ("b", "c")

Start with an empty DB: 从一个空的数据库开始:

在此处输入图片说明

Add one instance in the admin UI: 在管理界面中添加一个实例:

在此处输入图片说明

在此处输入图片说明

Fine so far. 到目前为止很好。 Now go to modify that instance: 现在去修改该实例:

在此处输入图片说明

在此处输入图片说明

Huh? 咦? What just happened? 刚刚发生了什么? Django just performed an INSERT when it should reliably be expected to perform an UPDATE. 当应该可靠地期望Django执行UPDATE时,它才执行INSERT。

Directly from How Django knows to UPDATE vs. INSERT : 直接从Django如何知道UPDATE与INSERT

You may have noticed Django database objects use the same save() method for creating and changing objects. 您可能已经注意到Django数据库对象使用相同的save()方法创建和更改对象。 Django abstracts the need to use INSERT or UPDATE SQL statements. Django提取了使用INSERT或UPDATE SQL语句的需求。 Specifically, when you call save(), Django follows this algorithm: 具体来说,当您调用save()时,Django遵循以下算法:

  • If the object's primary key attribute is set to a value that evaluates to True (ie, a value other than None or the empty string), Django executes an UPDATE. 如果对象的主键属性设置为计算结果为True的值(即,无或空字符串以外的值),则Django将执行UPDATE。
  • If the object's primary key attribute is not set or if the UPDATE didn't update anything, Django executes an INSERT. 如果未设置对象的主键属性,或者UPDATE未更新任何内容,则Django执行INSERT。

Now, this question will tell me that this is because a is a primary key. 现在, 这个问题将告诉我这是因为a是主键。 Firstly, I don't see that mentioned anywhere in the Django docs. 首先,我没有在Django文档中看到任何提到的内容。 Secondly, I'm not able to remove the primary_key attribute from a . 其次,我无法删除primary_key从属性a

I'm more interested in knowing why this is the case, what causes it internally with Django, and where it is documented (if anywhere)? 我更想知道为什么会这样,是什么原因导致它在Django内部发生,以及在哪里记录(如果有的话)? Are there other undocumented conditions wherein an INSERT gets done when you would expect an UPDATE to happen? 当您期望发生UPDATE时,是否还有其他未记录的条件可以完成INSERT?

https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.Field.primary_key https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.Field.primary_key

The primary key field is read-only. 主键字段是只读的。 If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one. 如果更改现有对象上的主键的值然后保存,则将在旧对象的旁边创建一个新对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM