使用单个查询集选择和更新数据库记录


139

如何在相同的条件下运行updateand select语句,queryset而不必执行两个查询:-一个选择对象-一个更新对象

SQL中的等效内容将类似于:

update my_table set field_1 = 'some value' where pk_field = some_value

Answers:


267

使用queryset 对象update方法

MyModel.objects.filter(pk=some_value).update(field1='some value')

95
只是一个合理的警告...如果您使用这种update方法,那么附加到该模型或其他“代码内容”的任何信号都不会对对象产生影响。只是一个被烧死的人的指针:)
毁灭者DMac'1

@DMactheDestroyer老兄感谢您提供的宝贵信息。那我们应该使用较旧的更新方式吗?(即)获取并保存?

@learning好家伙,这完全取决于您的情况。该update方法非常适合大规模更新,但使用时应在您的脑海中发出警告,您需要检查与该对象相连的所有信号,这些信号也可能需要手动触发
DMac The Destroyer

3
是否可以在更新功能中访问当前模型实例?喜欢MyModel.objects.filter(pk=some_value).update(field1=self.data)
Dipak

8
@DipakChandranP您应该问一个新问题,而不要对一个已有6年历史的问题发表评论。但是F()表达式可能是您想要的。
Daniel Roseman

70

Django数据库对象使用相同的save()方法创建和更改对象。

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

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

参考:https : //docs.djangoproject.com/en/1.9/ref/models/instances/


17

这个答案比较了以上两种方法。如果要在一行中更新许多对象,请执行以下操作:

# 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. 方法1更快,因为与方法2进行“ n + 1”个数据库查询相比,它仅进行一个数据库查询。(对于查询集中的n个项目)

  2. 第一种方法进行一个数据库查询,即UPDATE,第二种方法进行两个查询:SELECT然后是UPDATE。

  3. 代价是,假设您有任何触发器,例如更新updated_on或任何此类相关字段,则不会在直接更新即方法1上被触发。

  4. 方法1用于查询集,因此可以一次更新多个对象,而不是方法2。


关于1.-我认为查询结果会在第一次调用查询时被缓存,因此实​​际上仍然只有一个对DB的调用。
user2340939

2

只有在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()

我认为序列化器来自Djanog Rest Framework,而不是Django。
学徒

1
是的,但是Django form来自Django Proper。
Jamil Noyda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.