Как обновить модель внутри исключения функции представления и заставить транзакцию зафиксироваться в базе данных?
Мы пытаемся создать модель для контроля количества попыток доступа пользователя, а затем сделать вызов функции, которая может выбросить исключение, если, например, учетные данные не действительны. Если есть исключение, обновляем модель, увеличивая количество попыток на единицу, в противном случае обновляем модель другим способом. Каждый раз, когда мы находимся в ветке исключений, модель не создается и не обновляется. Мы пробовали использовать
s1 = transaction.savepoint()
transaction.savepoint_commit(s1)
and @transaction.non_atomic_requests
но результат все равно отбрасывается. Нет никакого способа избежать логики исключения. Версия Django: Django==2.2.24
access_attempt.py
from django.db import models
from django.utils.translation import gettext_lazy as _
class AccessAttempt(models.Model):
username = models.CharField(_("Username"), max_length=255, null=True, db_index=True)
failures_since_start = models.PositiveIntegerField(_("Failed Logins"))
validate_jwt_auth.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from .models.access_attempt import AccessAttempt
from rest_framework import status
from rest_framework.exceptions import AuthenticationFailed
@transaction.non_atomic_requests
def obtain_tokens(request, credentials):
attempt = AccessAttempt.objects.filter(username=credentials['username']).first()
if attempt is None:
attempt = AccessAttempt.objects.create(
username=credentials['username'],
failures_since_start=0
)
attempt.save()
failures = attempt.failures_since_start
print(failures)
if failures > 5:
return {'message': "Failed too many times"}, status.HTTP_403_FORBIDDEN
try:
with transaction.atomic():
payload = TokenObtainPairSerializer(context={'request':request}).validate(credentials)
attempt.failures_since_start=0
attempt.save()
return payload, status.HTTP_200_OK
except AuthenticationFailed:
attempt.failures_since_start += 1
attempt.save()
print(attempt.failures_since_start)
return {'message': "Unauthorized"}, status.HTTP_401_UNAUTHORIZED
views.py
def generate_auth(request):
b = json.loads(request.body)
if b['username'] is None or b['password'] is None:
return JsonResponse({'message': "Bad Request"}, status=status.HTTP_400_BAD_REQUEST)
payload, status = obtain_tokens(request, b)
return JsonResponse(payload, status=status)