Anubhav Bhattacharya
Anubhav Bhattacharya

Reputation: 70

Increment Model Field Inside Get Or Create Django

I am developing a music web application where I am trying to calculate the number of times a song was played. When the play button is clicked, a function called getLink() is called. Here, I try to use get_or_create to update the PlayCount model, like so.

h = PlayCount.objects.all()

    if len(h) == 0:
        u = PlayCount.objects.get_or_create(
            user=request.user.username,
            song=song,
            plays=1,
        )[0]
        u.save()

    else:

        flag = False

        for i in h:
            if i.song == song:
                u = PlayCount.objects.get_or_create(
                    user=request.user.username,
                    song=song,
                    plays=plays + 1,
                )[0]
                u.save()
                flag = True
                break
            else:
                pass

        if flag is False:
            u = PlayCount.objects.get_or_create(
                user=request.user.username,
                song=song,
                plays=1,
            )[0]
            u.save()
        else:
            pass

However, when I enter the else loop, 127.0.0.1:8000 returns play is not defined.

How may I proceed?

Upvotes: 0

Views: 366

Answers (1)

dirkgroten
dirkgroten

Reputation: 20672

I don't understand why you loop through all the PlayCount objects when all you need is to find the one for the specific user and song.

Note also that get_or_create will only find the specific object that matches all the parameters you pass to it, so get_or_create(user=..., song=..., plays=...) will try finding the one with the exact number of plays you specify which isn't what you want.

You only need to do this:

from django.db.models import F

play_counter, created = PlayCount.objects.get_or_create(
    user=request.user,
    song=song,
    defaults={'plays': 1})
if not created:
    play_counter.plays = F('plays') + 1
    play_counter.save()

So here we first fetch or create the counter for the particular song and user. If we create it, we set plays to 1 by setting it in the defaults parameter.

Then, if it is not created (i.e. it's an existing one), we increment plays by 1, using the F expression, which ensures it's updated in the database directly (and there's no risk of database inconsistency due if another request is updating the same value).

Upvotes: 2

Related Questions