2012-09-30 36 views
83

我想更新的Django的表格 - 在原始的SQL是这样的:如何用Django“批量更新”?

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

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

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

有没有更优雅的方式?

+1

您可能正在寻找批量插入。看看http://stackoverflow.com/questions/4294088/accelerate-bulk-insert-using-djangos-orm – Pramod

+0

我不喜欢插入新的数据 - 只需更新现有的。 – Thomas

+2

也许在select_for_update的帮助下? https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update –

回答

149

参考update功能Django文档中:https://docs.djangoproject.com/en/dev/ref/models/querysets/#update

总之,你应该能够使用:

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信号将被发射。
+21

也要注意,当不使用'save()方法的结果','用DateTimeField'领域'auto_now = True'(“修改”列)不会被更新。 – Arthur

+2

但是'ModelClass.objects.filter(name ='bar').update(name =“foo”)'不符合批量更新的目的,如果我对不同的ID有不同的数据,我怎么可以不使用循环? – Shashank

+0

@shihon我不确定我是否正确,但我为答案添加了示例。 –

24

考虑使用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 

更新:正如马克在评论这是不适合在更新数千行指出一旦。虽然它适用于小批量10至100。适合您的批次大小取决于您的CPU和查询的复杂性。这个工具更像是一辆手推车而不是一辆自卸车。

+5

我试过django-bulk-update,我个人不鼓励使用它。它在内部执行的是创建一个如下所示的单个SQL语句:UPDATE“table”SET“field”= CASE“id”WHEN%s THEN%s WHEN%s THEN%s [...] WHERE id in %s,%s,[...]);.对于少数行(当不需要批量更新时),这种情况是可以的,但有10,000个,查询非常复杂,postgres花费更多的时间在100%理解查询的CPU上,而不是节省写入磁盘的时间。 –

+0

@MarcGarcia好点。我发现许多开发人员在不知道其影响的情况下使用外部库 – Dejell

+2

@MarcGarcia我不同意批量更新不重要,只有在需要数千次更新时才真正需要。由于您提到的原因,使用它一次执行10,000行是不可取的,但使用它同时更新50行比使用50个单独的更新请求触及db要有效得多。 –