我想用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()
还有更优雅的方式吗?
我想用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()
还有更优雅的方式吗?
当前回答
IT返回在表中更新的对象数量。
update_counts = ModelClass.objects.filter(name='bar').update(name="foo")
您可以参考此链接获得关于批量更新和创建的更多信息。 批量更新和创建
其他回答
IT返回在表中更新的对象数量。
update_counts = ModelClass.objects.filter(name='bar').update(name="foo")
您可以参考此链接获得关于批量更新和创建的更多信息。 批量更新和创建
考虑使用GitHub上的django-bulk-update。
安装:pip Install django-bulk-update
实现:(代码直接取自项目ReadMe文件)
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和查询复杂性。这种工具与其说是自卸卡车,不如说是手推车。
如果你想在一个行集合上设置相同的值,你可以使用update()方法结合任何查询项来更新一个查询中的所有行:
some_list = ModelClass.objects.filter(some condition).values('id')
ModelClass.objects.filter(pk__in=some_list).update(foo=bar)
如果希望根据某些条件更新具有不同值的行集合,最好的情况下可以根据值对更新进行批处理。假设有1000行,其中您希望将其中一列设置为X个值之一,那么您可以预先准备批处理,然后只运行X个update-queries(每个都具有上面第一个示例的形式)+初始SELECT-query。
如果每一行都需要一个唯一的值,那么就无法避免每次更新只进行一次查询。如果在后一种情况下需要性能,可以考虑其他架构,如CQRS/事件源。
要更新相同的值,我们可以简单地使用这个
ModelClass.objects.filter(name = 'bar').update(name='foo')
用不同的值进行更新
ob_list = ModelClass.objects.filter(name = 'bar')
obj_to_be_update = []
for obj in obj_list:
obj.name = "Dear "+obj.name
obj_to_be_update.append(obj)
ModelClass.objects.bulk_update(obj_to_be_update, ['name'], batch_size=1000)
它不会每次都触发保存信号,而是将所有需要更新的对象保存在列表中,并一次触发更新信号。
这是我在网上找到的关于上述问题的有用内容
https://www.sankalpjonna.com/learn-django/running-a-bulk-update-with-django
低效的方式
model_qs= ModelClass.objects.filter(name = 'bar')
for obj in model_qs:
obj.name = 'foo'
obj.save()
有效的方法
ModelClass.objects.filter(name = 'bar').update(name="foo") # for single value 'foo' or add loop
使用bulk_update
update_list = []
model_qs= ModelClass.objects.filter(name = 'bar')
for model_obj in model_qs:
model_obj.name = "foo" # Or what ever the value is for simplicty im providing foo only
update_list.append(model_obj)
ModelClass.objects.bulk_update(update_list,['name'])
使用原子事务
from django.db import transaction
with transaction.atomic():
model_qs = ModelClass.objects.filter(name = 'bar')
for obj in model_qs:
ModelClass.objects.filter(name = 'bar').update(name="foo")
有人投赞成票吗?提前感谢:感谢您的关注;)