我想用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()
有更优雅的方式吗?
答案 0 :(得分:201)
<强> UPD 强> Django 2.2版本现在有一个bulk_update。
请参阅以下django文档部分
简而言之,您应该可以使用:
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
方法(所以如果你内部有一些逻辑则不会被触发)。 答案 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