Skip to content
Advertisement

How to run a forloop in django views.py?

I want to iterate over a queryset and if there is a new user added, I want to add some points for a specific user. To be more clear with what i am building: => I am writing a referral system logic in django.

The referral system works fine now, but what i want to implement is this. When i refer a user which are “user 2” and “user 3“, it is stored that I have referred two users, now I have also implemented a way to know if “user 2” or “user 3” which are referred by me: have gotten a new user referred by them (“user 2” or “user 3”).

Now what i want to achieve is this, when there is a new user from “user 2” or ” user 3 “ I want to add a some points to the “user 1” which referred the two user (“user 2” and “user 3“) that referred the new users.

I am thinking of using a forloop to iterate over the second_level_recommended, then add the point to the profile but it doesn’t seem to work or maybe the code that I wrote was wrong. This is the code that I wrote for the for-loop:

# for i in second_level_recommended:
    profile = Profile.objects.filter(recommended_by=request.user)
    profile.indirect_sign_up = profile.indirect_sign_up =+ 200

This is the code to check for the new users that “user 2” and “user 3” have referred belonging to “user 1”

views.py

my_recommended = Profile.objects.filter(recommended_by=request.user).values_list('user__id', flat=True)
second_level_recommended=Profile.objects.filter(recommended_by__in=my_recommended)

Then there is a forloop in the templates to display the second_level_recommended

NOTE: There is a Profile model which have these fields in it

class Profile(models.Model):
    user = models.OneToOneField(User, ...)
    ...
    code = models.CharField(max_length=100, ...)
    recommended_by = models.ForeignKey(User, ...)

Advertisement

Answer

It’s hard to tell if this is exactly what you want without seeing more context of your code, but I will take a stab at answering…

Instead of a for loop, we are going to use this technique: https://docs.djangoproject.com/en/4.0/ref/models/expressions/#f-expressions

(see also https://docs.djangoproject.com/en/4.0/ref/models/instances/#updating-attributes-based-on-existing-fields)

from django.db.models import F


my_recomended = Profile.objects.filter(recommended_by=request.user).values_list('user__id', flat=True)
second_level_recommended=Profile.objects.filter(recommended_by__in=my_recomended)

second_level_recommended.update(indirect_sign_up=F('indirect_sign_up') + 200)

This means we can update all the matched users in second_level_recommended queryset in a single db operation.

Otherwise if you use a for loop it is probably slower, but more importantly you run the risk of a “race condition”.

The race condition would be where you fetch the db row into memory, as a Django model instance, update value on the model instance based on the value just fetched, then save it back to the db. So you can get a problem where someone requests the same view for same or related user at the same time – both requests get the same old value and add 200 to it, but the end result of two requests is just +200 instead of +400.

Using an update query avoids that because the operation is “atomic” in the db – we tell the database to add 200 to each row instead of doing it ourselves one by one in Python code. If two requests come in almost simultaneously the db will ensure they execute serially, so first one +200 and then a second +200.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement