1

I need to add a restriction on account login attempts to my django site, I found the popular django-axes library, followed the documentation and code examples, but when I try to log in to my account (whether the password is correct or not) I get the error AxesBackend requires a request as an argument to authenticate even though my code follows the instructions exactly and I'm passing the request. Here is all the code that is somehow related to this:

settings.py

INSTALLED_APPS = [
    ...
    'axes',
]

MIDDLEWARE = [
    ...
    'axes.middleware.AxesMiddleware',
]

AXES_FAILURE_LIMIT =  4
AXES_RESET_ON_SUCCESS = True
AXES_COOLOFF_TIME = 1

AUTHENTICATION_BACKENDS = [
   'axes.backends.AxesBackend', # Axes must be first
   'django.contrib.auth.backends.ModelBackend',
]

AUTH_USER_MODEL = "users.User"
LOGIN_URL = "/user/login/"

views.py

from django.contrib import auth, messages

def login(request):

    if request.method == "POST":
        form = UserLoginForm(data=request.POST)
        if form.is_valid():
            username = request.POST["username"]
            password = request.POST["password"]
            user = auth.authenticate(request=request, username=username, password=password)

            if user:
                auth.login(request, user)

                redirect_page = request.POST.get("next", None)

                if redirect_page and redirect_page != reverse("user:logout"):
                    return HttpResponseRedirect(request.POST.get("next"))

                return HttpResponseRedirect(reverse("main:main_page"))
    else:

        form = UserLoginForm()

    context = {"title": "Вход", "form": form}

    return render(request, "users/login.html", context)

forms.py

from django import forms
from django.contrib.auth.forms import (
    AuthenticationForm,
    UserCreationForm,
    UserChangeForm,
)
from users.models import User


class UserLoginForm(AuthenticationForm):

    username = forms.CharField()
    password = forms.CharField()

    class Meta:
        model = User
        fields = ["username", "password"]

versions libs

Django==5.0.4
django-axes==6.5.2

I would be very grateful for your help!

Full Traceback

Traceback (most recent call last):
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\bismuth\users\views.py", line 17, in login
    if form.is_valid():
       ^^^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\forms\forms.py", line 197, in is_valid    
    return self.is_bound and not self.errors
                                 ^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\forms\forms.py", line 192, in errors      
    self.full_clean()
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\forms\forms.py", line 328, in full_clean  
    self._clean_form()
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\forms\forms.py", line 349, in _clean_form 
    cleaned_data = self.clean()
                   ^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\contrib\auth\forms.py", line 250, in clean
    self.user_cache = authenticate(
                      ^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\views\decorators\debug.py", line 75, in sensitive_variables_wrapper
    return func(*func_args, **func_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\django\contrib\auth\__init__.py", line 79, in authenticate
    user = backend.authenticate(request, **credentials)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\axes\helpers.py", line 615, in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\danii\OneDrive\Рабочий стол\coins\Project Bismuth\venv\Lib\site-packages\axes\backends.py", line 46, in authenticate      
    raise AxesBackendRequestParameterRequired(
axes.exceptions.AxesBackendRequestParameterRequired: AxesBackend requires a request as an argument to authenticate
[07/Oct/2024 10:27:42] "POST /user/login/ HTTP/1.1" 500 125895
5
  • Can you share the full traceback, so with the error lines above the one you posted? Commented Oct 6, 2024 at 13:21
  • @willeM_ VanOnsem Of course! Added a full Traceback to the body of the question Commented Oct 7, 2024 at 3:33
  • Can you share the UserLoginForm? Commented Oct 7, 2024 at 9:09
  • Yes: ` from django import forms from django.contrib.auth.forms import ( AuthenticationForm, UserCreationForm, UserChangeForm, ) from users.models import User class UserLoginForm(AuthenticationForm): username = forms.CharField() password = forms.CharField() class Meta: model = User fields = ["username", "password"] ` Commented Oct 7, 2024 at 14:15
  • Please edit the question. Commented Oct 7, 2024 at 14:16

1 Answer 1

1

The reason it fails is because your UserLoginForm already tries to authenticate(), and that fails because it has no request object.

The good news is: we can let the form handle it with the request, like:

from django.urls import redirect


def login(request):
    if request.method == 'POST':
        form = UserLoginForm(request=request, data=request.POST)
        if form.is_valid():
            user = form.get_user()
            if user:
                auth.login(request, user)
                redirect_page = request.POST.get('next', None)

                if redirect_page and redirect_page != reverse('user:logout'):
                    return HttpResponseRedirect(request.POST.get('next'))
                return redirect('main:main_page')
    else:
        form = UserLoginForm()
    context = {'title': 'Вход', 'form': form}
    return render(request, 'users/login.html', context)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! You helped me a lot and I'm glad that such a pro like you did it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.