Updating selection of objects, each with a different value in bulk (Django)

后端 未结 2 461
清酒与你
清酒与你 2021-01-02 00:02

Imagine I have a python dictionary where keys are existing user ids, and values are scores to be added to those users\' existing scores.

For example: {1: 1580

相关标签:
2条回答
  • 2021-01-02 00:09

    Something like that:

    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)
    

    More on this here

    You can take a look at this answer too.

    [UPDATE]:

    TL;DR: It'll not make one db query but it will be faster cause each query lacks the database overhead.

    As the docs and @ahmed in his answer say:

    Django’s default behavior is to run in autocommit mode. Each query is immediately committed to the database, unless a transaction is active.

    By using with transaction.atomic() all the inserts are grouped into a single transaction. The time needed to commit the transaction is amortized over all the enclosed insert statements and so the time per insert statement is greatly reduced.

    0 讨论(0)
  • 2021-01-02 00:26

    transaction.atomic() proposed by @nik_m is good idea, but also you should get records from database in single request.

    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])
    
    0 讨论(0)
提交回复
热议问题