ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Django 中使用单个查询集选择记录并更新它?

如何在同一个 queryset 上运行 updateselect 语句,而不必执行两个查询:- 一个用于选择对象 - 一个用于更新对象

SQL 中的等价物类似于:

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

A
Adolfo

使用查询集 object update method

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

只是一个公平的警告......如果您使用这样的 update 方法,那么附加到该模型或其他“代码内容”的任何信号都不会针对对象运行。只是来自被烧伤的人的指示:)
@learning 好伙计,这完全取决于您的情况。 update 方法非常适合大规模更新,但是当您使用它时,它应该会在您的脑海中引发警告,您需要查看附加到该对象的任何可能还需要手动触发的信号
是否可以在更新功能中访问当前模型实例?像MyModel.objects.filter(pk=some_value).update(field1=self.data)
@DipakChandranP您应该提出一个新问题,而不是对一个六岁的问题发表评论。但是 F() 表达式可能是你想要的。
@DMactheDestroyer 9 年后,我终于明白你的评论了。 stackoverflow.com/a/71688507/417899
S
Slipstream

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/


P
Pransh Tiwari

这个答案比较了上述两种方法。如果要在一行中更新多个对象,请使用:

# 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 的情况下。


关于 1. - 我认为查询结果在第一次调用查询时被缓存,因此实际上仍然只有一次调用 DB。
R
Riyas Ac

第一种方法

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'})

R
Roman-Stop RU aggression in UA

如果您需要根据旧字段值设置新值,请执行以下操作:

update my_table set field_1 = field_1 + 1 where pk_field = some_value

使用 query expressions

MyModel.objects.filter(pk=some_value).update(field1=F('field1') + 1)

这将自动执行更新,即使用对数据库的一个更新请求而不先读取它。


J
Jamil Noyda

只有在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。
是的,但是 Django form 来自 Django Proper。
c
cyberfly

接受的答案效果很好,但它带来了一些不需要的副作用。

例如,您正在使用 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