如何使用Django进行“批量更新”?

时间:2012-09-30 12:30:07

标签: django django-models

我想用Django更新一个表 - 在原始SQL中就像这样:

update tbl_name set name = 'foo' where name = 'bar'

我的第一个结果是这样的 - 但这很讨厌,不是吗?

list = ModelClass.objects.filter(name = 'bar')
for obj in list:
    obj.name = 'foo'
    obj.save()

有更优雅的方式吗?

5 个答案:

答案 0 :(得分:201)

<强> UPD Django 2.2版本现在有一个bulk_update

请参阅以下django文档部分

  

Updating multiple objects at once

简而言之,您应该可以使用:

ModelClass.objects.filter(name='bar').update(name="foo")

您还可以使用F个对象来执行增加行的操作:

from django.db.models import F
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

请参阅文档:https://docs.djangoproject.com/en/1.9/topics/db/queries/

但请注意:

  • 这不会使用ModelClass.save方法(所以如果你内部有一些逻辑则不会被触发)。
  • 不会发出任何django信号。

答案 1 :(得分:29)

考虑使用django-bulk-update找到here on GitHub

安装:pip install django-bulk-update

实施:(代码直接取自项目自述文件)

from bulk_update.helper import bulk_update

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()

for person in people:
    r = random.randrange(4)
    person.name = random_names[r]

bulk_update(people)  # updates all columns using the default db

更新:正如Marc在评论中指出的那样,这不适合一次更新数千行。虽然它适用于较小批量的10到100年代。适合您的批处理大小取决于您的CPU和查询复杂性。这个工具更像是手推车而不是自卸车。

答案 2 :(得分:6)

Django 2.2版本现在具有bulk_update方法(release notes)。

https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-update

示例:

# get a pk: record dictionary of existing records
updates = YourModel.objects.filter(...).in_bulk()
....
# do something with the updates dict
....
if hasattr(YourModel.objects, 'bulk_update') and updates:
    # Use the new method
    YourModel.objects.bulk_update(updates.values(), [list the fields to update], batch_size=100)
else:
    # The old & slow way
    with transaction.atomic():
        for obj in updates.values():
            obj.save(update_fields=[list the fields to update])

答案 3 :(得分:1)

如果要在一组行上设置相同的值,则可以将update()方法与任何查询词结合使用来更新一个查询中的所有行:

some_list = ModelClass.objects.filter(some condition).values('id')
ModelClass.objects.filter(pk__in=some_list).update(foo=bar)

如果您要根据某些条件更新具有不同值的行的集合,则最好在情况下根据值批量更新。假设您有1000行要在其中设置X值之一的列,那么您可以预先准备批处理,然后仅运行X更新查询(每个查询都具有上述第一个示例的形式)+初始SELECT -查询。

如果每一行都需要一个唯一值,则无法避免每次更新都进行一次查询。如果在后一种情况下需要性能,也许可以考虑使用其他架构,例如CQRS /事件源。

答案 4 :(得分:1)

IT返回表中更新的对象数。

update_counts = ModelClass.objects.filter(name='bar').update(name="foo")

您可以参考此链接以获取有关批量更新和创建的更多信息。 Bulk update and Create