Проблема с формой входа в Django: Форма недействительна, несмотря на правильные учетные данные

Я столкнулся с проблемой, связанной с моей формой входа в Django. Несмотря на предоставление правильных учетных данных, форма постоянно возвращается как недействительная. Вот подробное описание моей установки и проблемы, с которой я столкнулся.

Описание

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

form.py


    from django import forms
    from .models import UserRegister
    from django.contrib.auth.forms import UserCreationForm , AuthenticationForm
    from django.core.exceptions import ValidationError
    
    class UserRegisterForm(UserCreationForm):
        username = forms.CharField(max_length=50, required=True, widget=forms.TextInput(attrs={'placeholder': 'Username', 'class': 'input-group'}))
        email = forms.EmailField(max_length=70, required=True, widget=forms.EmailInput(attrs={'placeholder': 'Email', 'class': 'input-group'}))
        password1 = forms.CharField(max_length=128, required=True, widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'class': 'input-group', 'id': 'password'}))
        password2 = forms.CharField(max_length=128, required=True, widget=forms.PasswordInput(attrs={'placeholder': 'Confirm Password', 'class': 'input-group', 'id': 'password'}))
    
        class Meta:
            model = UserRegister
            fields = ['username', 'email', 'password1', 'password2']
            error_messages = {
            "password_mismatch": "Conform Password Does not match with Password"
        }
    
        def clean_email(self):
            email = self.cleaned_data.get('email')
            if UserRegister.objects.filter(email=email).exists():
                raise ValidationError('This email address is already in use.')
            return email
        
        def clean_username(self):
            username = self.cleaned_data.get('username')
            if UserRegister.objects.filter(username=username).exists():
                raise ValidationError('This username is already in use.')
            return username
    
        def clean_password2(self):
            password1 = self.cleaned_data.get('password1')
            password2 = self.cleaned_data.get('password2')
            if password1 and password2 and password1 != password2:
                raise ValidationError(self.error_messages['password_mismatch'], code='password_mismatch')
            return password2
    
    
    class UserLoginForm(AuthenticationForm):
        username = forms.CharField(max_length=50, required=True ,widget=forms.TextInput(attrs={'placeholder':'Username','class':'input-group'}))
        password = forms.CharField(max_length=128,required=True,widget=forms.PasswordInput(attrs={'placeholder':'Password','class':'input-group'}))

views.py

urls.py


    from django.urls import path
    from . import views
    
    urlpatterns=[path("Home",views.Home),
                 path("SignUp",views.SignUp,name='Signup'),
                 path("Products",views.Products,name="Products"),
                 path('Products/<slug:slug>',views.about_product,name="About Product"),
                 path("Login",views.Login,name='Log')]

login.html


    {% extends "base.html" %}
    
    {% block title %}
    Login
    {% endblock %}
    
    {% load static %}
    
    {% block css_files %}
    <link rel="stylesheet" href="{% static 'reviews/Login.css' %}">
    {% endblock %}
    
    {% block content %}
        <form method="POST" action="{% url 'Log' %}">
            {% csrf_token %}
            <div class="input-section">
                <div class="input-group">
                    <label for="{{ form.username.id_for_label }}">Username</label>
                    {{ form.username }}
                    {% if form.username.errors %}
                        <div class="error-message">
                            {% for error in form.username.errors %}
                                <p>{{ error }}</p>
                            {% endfor %}
                        </div>
                    {% endif %}
                </div>
    
                <div class="input-group">
                    <label for="{{ form.password.id_for_label }}">Password</label>
                    {{ form.password }}
                    {% if form.password.errors %}
                        <div class="error-message">
                            {% for error in form.password.errors %}
                                <p>{{ error }}</p>
                            {% endfor %}
                        </div>
                    {% endif %}
                </div>
                <button class="submit-btn" type="submit">Login</button>
            </div>
        </form>
    {% endblock %}

Я полагаю, что у вас две ошибки в Login() представлении.

Во-первых, вы получаете из формы не тот элемент:

password=form.cleaned_data.get('password')

В форме нет поля с именем password - в ней есть password1 и password2.

Из-за этого метод authenticate() всегда будет возвращать None.

И это ваша вторая ошибка - у вас нет никакой обработки для этого случая:

user = authenticate(
    request, 
    username=form.cleaned_data.get('username'), 
    password=form.cleaned_data.get('password')
)
if user is not None:
    login(request, user)
    return HttpResponseRedirect('/Products')
# but what if user is None? ...

Вы обрабатываете только случай, когда вход в систему был успешным, т.е. пользователь не None. Конечно, вы должны вызывать какую-то ошибку, если вход в систему не был успешным?

Я полагаю, что у вас также может быть ошибка в определении формы:

class UserRegisterForm(UserCreationForm):
    username = forms.CharField(max_length=50, required=True, widget=forms.TextInput(attrs={'placeholder': 'Username', 'class': 'input-group'}))
    email = forms.EmailField(max_length=70, required=True, widget=forms.EmailInput(attrs={'placeholder': 'Email', 'class': 'input-group'}))
    password1 = forms.CharField(max_length=128, required=True, widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'class': 'input-group', 'id': 'password'}))
    password2 = forms.CharField(max_length=128, required=True, widget=forms.PasswordInput(attrs={'placeholder': 'Confirm Password', 'class': 'input-group', 'id': 'password'}))

Оба виджета PasswordInput имеют 'id': 'password' в attrs виджета. Это, конечно, неправильно? Они не могут иметь одинаковый id.

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