如何在同一个 queryset
上运行 update
和 select
语句,而不必执行两个查询:- 一个用于选择对象 - 一个用于更新对象
SQL 中的等价物类似于:
update my_table set field_1 = 'some value' where pk_field = some_value
Django 数据库对象使用相同的 save() 方法来创建和更改对象。
obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()
Django 如何知道 UPDATE 与 INSERT 如果对象的主键属性设置为一个计算结果为 True 的值(即,除了 None 或空字符串之外的值),Django 执行 UPDATE。如果对象的主键属性没有设置或者 UPDATE 没有更新任何东西,Django 执行一个 INSERT。
参考:https://docs.djangoproject.com/en/1.9/ref/models/instances/
这个答案比较了上述两种方法。如果要在一行中更新多个对象,请使用:
# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')
否则,您将不得不遍历查询集并更新单个对象:
#Approach 2
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
obj.field2 = 'cool'
obj.save()
方法 1 更快,因为它只进行一次数据库查询,而方法 2 进行“n+1”数据库查询。 (对于查询集中的 n 项)第一种方法进行一次数据库查询,即 UPDATE,第二种方法进行两次:SELECT 和 UPDATE。权衡是,假设您有任何触发器,例如更新 updated_on 或任何此类相关字段,它不会在直接更新时触发,即方法 1。方法 1 用于查询集,因此可以一次更新多个对象,而不是在方法 2 的情况下。
第一种方法
MyTable.objects.filter(pk=some_value).update(field1='some value')
第二种方法
q = MyModel.objects.get(pk=some_value)
q.field1 = 'some value'
q.save()
第三种方法
通过使用 get_object_or_404
q = get_object_or_404(MyModel,pk=some_value)
q.field1 = 'some value'
q.save()
第四种方法
如果您需要,如果 pk=some_value
存在,则 update
它,否则 create
使用 update_or_create
新建一个。
MyModel.objects.update_or_create(pk=some_value,defaults={'field1':'some value'})
如果您需要根据旧字段值设置新值,请执行以下操作:
update my_table set field_1 = field_1 + 1 where pk_field = some_value
MyModel.objects.filter(pk=some_value).update(field1=F('field1') + 1)
这将自动执行更新,即使用对数据库的一个更新请求而不先读取它。
只有在serializer
的情况下,您才能以非常简单的方式进行更新!
my_model_serializer = MyModelSerializer(
instance=my_model, data=validated_data)
if my_model_serializer.is_valid():
my_model_serializer.save()
仅适用于 form
件事情!
instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
form.save()
Django form
来自 Django Proper。
接受的答案效果很好,但它带来了一些不需要的副作用。
例如,您正在使用 imageField,update() 将起作用并更新其他数据,但不会更新您的 imageField 数据
class ProfileSetting(models.Model):
first_name = models.CharField(blank=True)
logo = models.ImageField(blank=True, null=True, upload_to="profile/logo/")
update_data = {
"first_name": "john",
"logo": request.FILES['logo'] # logo will not be properly update
}
ProfileSetting.objects.filter(pk=some_value).update(**update_data)
这是一个很好解释的例子Django ImageField is not updating when update() method is used
不定期副业成功案例分享
update
方法,那么附加到该模型或其他“代码内容”的任何信号都不会针对对象运行。只是来自被烧伤的人的指示:)update
方法非常适合大规模更新,但是当您使用它时,它应该会在您的脑海中引发警告,您需要查看附加到该对象的任何可能还需要手动触发的信号MyModel.objects.filter(pk=some_value).update(field1=self.data)