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

时间:2019-05-19 21:27:54

标签: python django

考虑以下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)

与此类别一起在admin中注册:

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

从一个空的数据库开始:

enter image description here

在管理界面中添加一个实例:

enter image description here

enter image description here

到目前为止还不错。现在去修改该实例:

enter image description here

enter image description here

嗯?刚刚发生了什么?当应该可靠地期望Django执行UPDATE时,它才执行INSERT。

直接来自How Django knows to UPDATE vs. INSERT

  

您可能已经注意到Django数据库对象使用相同的save()方法创建和更改对象。 Django提取了使用INSERT或UPDATE SQL语句的需求。具体来说,当您调用save()时,Django会遵循以下算法:

     
      
  • 如果对象的主键属性设置为计算结果为True的值(即,无或空字符串以外的值),则Django将执行UPDATE。
  •   
  • 如果未设置对象的主键属性,或者UPDATE未更新任何内容,则Django将执行INSERT。
  •   

现在,this question会告诉我这是因为a是主键。首先,我没有在Django文档中看到任何提到的内容。其次,我无法从primary_key中删除a属性。

我更想知道为什么会这样,是什么原因导致它在Django内部发生,以及在哪里被记录(如果有的话)?是否还有其他未记录的条件可以完成INSERT?您何时会期望发生更新?

1 个答案:

答案 0 :(得分:3)

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

  

主键字段是只读的。如果更改现有对象上的主键的值然后保存,则将在旧对象的旁边创建一个新对象。