How to "create or update" using F object?

Viewed 614

I need to create LeaderboardEntry if it is not exists. It should be updated with the new value (current + new) if exists. I want to achieve this with a single query. How can I do that?

Current code looking like this: (2 queries)

reward_amount = 50

LeaderboardEntry.objects.get_or_create(player=player)
LeaderboardEntry.objects.filter(player=player).update(golds=F('golds') + reward_amount)

PS: Default value of "golds" is 0.

3 Answers

you can have one query hit less with the defaults :

reward_amount = 50

leader_board, created = LeaderboardEntry.objects.get_or_create(
    player=player,
    defaults={
        "golds": reward_amount,
    }
)

if not created:
    leader_board.golds += reward_amount
    leader_board.save(update_fields=["golds"])

I think your problem is the get_or_create() method so it return back a tuple with two values, (object, created) so you have to recieve them in your code as following:

reward_amount = 50

entry, __ = LeaderboardEntry.objects.get_or_create(player=player)
entry.golds += reward_amount
entry.save()

It will work better than your actual code, just will avoid make two queries.

Of course the save() method will hit again your database.

You can solve this with update_or_create:

LeaderboardEntry.objects.update_or_create(
    player=player,
    defaults={
        'golds': F('golds') + reward_amount
    }
)

EDIT:

Sorry, F expressions in update_or_create are not yet supported.

Related