更新对象的选择,每个对象具有不同的批量值(Django)

时间:2017-03-11 08:10:28

标签: django django-orm

想象一下,我有一个python字典,其中键是现有用户ID,值是要添加到这些用户现有分数的分数。

例如:{1: 1580, 4: 540, 2: 678}(这可以延伸到n k,v对)

我需要更新所有这些用户对象的分数(updated_score = original_score + new_score)。一种方法是迭代,如下:

from django.db.models import F
scores = {1: 1580, 4: 540, 2: 678}
for user_id,score_to_add in scores.iteritems():
    UserProfile.objects.filter(user_id=user_id).update(score=F('score')+score_to_add)

但那是多个数据库调用。我可以一次通话吗?一个说明性的例子会很棒。正如您所猜测的那样,这是一个Django项目。

2 个答案:

答案 0 :(得分:7)

类似的东西:

from django.db.models import F
from django.db import transaction

with transaction.atomic():
    scores = {1: 1580, 4: 540, 2: 678}
    for user_id,score_to_add in scores:
        UserProfile.objects.filter(user_id=user_id).update(score=F('score')+score_to_add)

有关此here

的更多信息

您也可以查看this answer

[更新]:

TL; DR:它不会进行一次数据库查询,但会更快,因为每个查询都缺少数据库开销。

正如his answer中的文档和@ahmed所说:

  

Django的默认行为是在自动提交模式下运行。每个查询都是   除非事务是,否则立即提交到数据库   活性

     

通过使用with transaction.atomic(),所有插入都被分组为a   单笔交易。提交交易所需的时间是   在所有随附的插入语句中摊销,因此每个时间   插入语句大大减少了。

答案 1 :(得分:0)

@nik_m提出的

transaction.atomic()是个好主意,但你也应该在单个请求中从数据库中获取记录。

from django.db.models import F
from django.db import transaction

with transaction.atomic():
    scores = {1: 1580, 4: 540, 2: 678}
    users_to_update = UserProfile.objects.filter(
        user_id__in=scores.keys()
    ) 
    for user in users_to_update:
        user.update(score=F('score') + scores[user.user_id])