Показ капчи после 5 неверных попыток входа в систему с помощью django-axes

Я начинающий Django и у меня есть страница входа и с капчей, которая работает отлично, однако я хотел бы показывать капчу в шаблоне страницы входа только после того, как пользователь ввел неправильные данные для входа после 5 попыток.

В моем шаблоне есть тег include для моей капчи, которую я предпочитаю отображать этим методом, но не уверен, что это возможно, но думал, что смогу реализовать через создание 2 отдельных представлений/шаблонов, так как мне казалось, что я смогу это сделать, но, похоже, нет.

Урлы

from django.urls import path, include

from django.contrib.auth import views as auth_views

from . import views
from .views import RequestPasswordResetEmail, CompletePasswordReset
#from .forms import EmailValidationOnForgotPassword

urlpatterns = [
    path('login/', views.loginpage, name="login"),
    path('login-captcha/', views.logincaptcha, name="logincaptcha"),
    path('logout/', views.logoutuser, name="logout"),
    path('register/', views.registerpage, name="register"),
    path('verify-email/<uidb64>/<token>', views.verify_email, name="verify_email"),
    path('activate-account/<uidb64>/<token>', views.activate_account, name="activate_account"),

    path('set-new-password/<uidb64>/<token>', CompletePasswordReset.as_view(), name="reset-user-password"),

    path("request-reset-link/", RequestPasswordResetEmail.as_view(), name="request-password"),

]

Виды

from django.conf import settings
from .decorators import check_recaptcha
from axes.decorators import axes_dispatch
from django.shortcuts import render, redirect
from django.contrib import messages, auth
from django.contrib.auth import authenticate, login, logout
from django.views import View


@axes_dispatch
def loginpage(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')


        user = authenticate(request, username=username, password=password)

        if user is not None:

            if user.is_active and settings.AXES_FAILURE_LIMIT < 3:
                login(request, user)
                return redirect('home')

            elif settings.AXES_FAILURE_LIMIT > 3:
                return redirect('logincaptcha')
            else:
                messages.error(request, 'Account for this User has not been Activated.')
        else:
            messages.error(request, 'Username or Password is Incorrect.')

    context = {}
    return render(request, 'login.html', context)


def logincaptcha(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(request, username=username, password=password)

        if user is not None:

            if user.is_active:
                login(request, user)
                return redirect('home')
            else:
                messages.error(request, 'Account for this User has not been Activated.')
        else:
            messages.error(request, 'Username or Password is Incorrect.')

    context = {}
    return render(request, 'login_captcha.html', context)

Шаблон logincaptcha (шаблон страницы входа точно такой же, но не включает тег captcha)

{% extends 'base.html' %}

{% block title %}User Login{% endblock %}

{% block content %}
    <div class="d-flex justify-content-center">
        <h3 id="form-title">Login</h3>
    </div>
    <div class="d-flex justify-content-center form_container">
        <form method="POST" action="">
            {% csrf_token %}
            
            <div align="center">
                <div class="input-group mb-2">
                    <div class="input-group-append">
                        <span class="input-group-text"><i class="fas fa-user"></i></span>
                    </div>
                    <input type="text" name="username" placeholder="Email" class="form-control">
                </div>
                
                
                <div class="input-group mb-3">
                    <div class="input-group-append">
                        <span class="input-group-text"><i class="fas fa-key"></i></span>
                    </div>
                    <input type="password" name="password" placeholder="Password" class="form-control">
                </div>
            </div>
            
            
            {% include 'recaptcha.html' %}
            
            
            <div class="d-flex justify-content-center mt-3 login_container">
                <input class="btn login_btn" type="submit" value="Login">
            </div>
        
        
        </form>
    </div>
    {% include 'messages.html' %}
    <div class="input-group mb-1">
    </div>
    <div class="mt-1">
        <div class="d-flex justify-content-center links">
            Don't have an account? <a href="{% url 'register' %}" class="ml-2">Sign Up</a>
        </div>
        <div class="d-flex justify-content-center links">
            Forgot Password? <a href="{% url 'request-password' %}" class="ml-2">Reset Password</a>
        </div>
    </div>

{% endblock content %}

Мне удалось решить эту проблему, обновив декоратор таким образом, чтобы он отображал сообщение об ошибке только после 4 неудачных попыток входа в систему следующим образом:

recaptcha decorator.py

from django.conf import settings
from django.contrib import messages
from django.db.models import Sum
from functools import wraps


from axes.attempts import (
    get_user_attempts,
)

import requests


def check_recaptcha(view_func, credentials: dict = None):
    @wraps(view_func)
    def _wrapped_view(request, *args, **kwargs):

        attempts_list = get_user_attempts(request, credentials)

        attempt_count = max(
            (
                    attempts.aggregate(Sum("failures_since_start"))[
                        "failures_since_start__sum"
                    ]
                    or 0
            )
            for attempts in attempts_list
        )
        print(attempt_count)

        attempt_count = attempt_count + 1



        request.recaptcha_is_valid = None
        if request.method == 'POST':
            recaptcha_response = request.POST.get('g-recaptcha-response')
            data = {
                'secret': settings.RECAPTCHA_PRIVATE_KEY,
                'response': recaptcha_response
            }
            r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
            result = r.json()
            if result['success']:
                request.recaptcha_is_valid = True
            else:
                request.recaptcha_is_valid = False

                if attempt_count > 3+1:
                    messages.error(request, 'Invalid reCAPTCHA. Please try again.')


        return view_func(request, *args, **kwargs)
    return _wrapped_view

Все работает так, как мне нужно!

Вернуться на верх