Как запустить цикл forloop в django views.py?
Я хочу взаимодействовать с набором запросов и если добавляется новый пользователь, я хочу добавить несколько очков для конкретного пользователя. Чтобы быть более ясным с тем, что я создаю: => Я пишу логику реферальной системы на django. Сейчас реферальная система работает хорошо, но я хочу реализовать следующее. Когда я ссылаюсь на пользователя "user 2" и "user 3", сохраняется, что я ссылаюсь на two users, теперь я также реализовал способ узнать, если "user 2" или "user 3", которые ссылаются на меня: получили нового пользователя, ссылающегося на них ("user 2" или "user 3").
Теперь я хочу добиться следующего, когда появляется новый пользователь "пользователь 2" или "пользователь 3" я хочу добавить несколько пунктов к "пользователь 1", который ссылался на двух пользователей ("user 2" и "user 3"), которые ссылались на новых пользователей.
Я думаю использовать цикл forloop для итерации second_level_recommended
, затем добавить точку в профиль, но, похоже, это не работает, или, возможно, код, который я написал, был неправильным. Вот код, который я написал для цикла forloop ниже
# for i in second_level_recommended:
profile = Profile.objects.filter(recommended_by=request.user)
profile.indirect_sign_up = profile.indirect_sign_up =+ 200
Вот код для проверки новых пользователей, которые "user 2" и "user 3" назвали себя принадлежащими "user 1". views.py
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)
Затем в шаблонах есть цикл forloop для отображения second_level_recommended
NOTE: Существует Profile
модель, в которой есть эти поля
class Profile(models.Model):
user = models.OneToOneField(User, ...)
...
code = models.CharField(max_lenght=100, ...)
recommended_by = models.ForeignKey(User, ...)
Если нужен код того, как я регистрирую пользователей для рефералов, то вот он views.py
def registerRef(request, *args, **kwargs):
profile_id = request.session.get('ref_profile')
print('profile_id', profile_id)
code = str(kwargs.get('ref_code'))
try:
profile = Profile.objects.get(code=code)
request.session['ref_profile'] = profile.id
print('Referer Profile:', profile.id)
except:
pass
print("Session Expiry Date:" + str(request.session.get_expiry_age()))
form = UserRegisterForm(request.POST or None)
if form.is_valid():
if profile_id is not None:
recommended_by_profile = Profile.objects.get(id=profile_id)
ref_earn = InvestmentPackageID.objects.get()
instance = form.save()
registered_user = User.objects.get(id=instance.id)
registered_profile = Profile.objects.get(user=registered_user)
registered_profile.recommended_by = recommended_by_profile.user
registered_profile.save()
else:
instance = form.save()
registered_user = User.objects.get(id=instance.id)
profile = Profile.objects.get(user=registered_user)
profile.save()
username = form.cleaned_data.get('email')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
login(request, user)
return redirect('core:index')
context = {'form':form}
return render(request, 'userauths/sign-up.html', context)
Трудно сказать, является ли это именно тем, что вы хотите, не видя больше контекста вашего кода, но я попробую ответить...
Вместо цикла for мы будем использовать эту технику: https://docs.djangoproject.com/en/4.0/ref/models/expressions/#f-expressions
(см. также 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)
Это означает, что мы можем обновить всех совпадающих пользователей в second_level_recommended
наборе запросов в одной операции с БД.
В противном случае, если вы используете цикл for, это, вероятно, будет медленнее, но, что более важно, вы рискуете столкнуться с "состоянием гонки".
Условием гонки будет ситуация, когда вы получаете строку из базы данных в память, как экземпляр модели Django, обновляете значение в экземпляре модели на основе только что полученного значения, а затем сохраняете его обратно в базу данных. Таким образом, вы можете получить проблему, когда кто-то запрашивает одно и то же представление для одного и того же или связанного пользователя одновременно - оба запроса получают одно и то же старое значение и добавляют к нему 200, но конечным результатом двух запросов будет просто +200 вместо +400.
Использование запроса update
позволяет избежать этого, поскольку операция в базе данных "атомарна" - мы говорим базе данных database добавить 200 к каждой строке вместо того, чтобы делать это самостоятельно по очереди в коде Python. Если два запроса придут почти одновременно, база данных обеспечит их последовательное выполнение, так что сначала один +200, а затем второй +200.