Django内置AuthForm验证失败,请求错误排查帮助
导致form.is_valid()始终返回False的问题分析与修复
1. 自定义User模型的核心错误
AbstractUser已经内置了加密存储的password字段,你额外添加的password1和password2属于冗余设计,不仅会导致密码存储逻辑混乱(明文存储风险),还会和Django内置认证逻辑冲突。登录认证只需要使用AbstractUser自带的password字段即可。
修复后的models.py:
from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): ''' Model that represents a user in the database ''' first_name = models.CharField(max_length=50, null=False, blank=False) last_name = models.CharField(max_length=50, null=False, blank=False) username = models.CharField(max_length=50, null=False, blank=False, unique=True) email = models.EmailField(null=False, blank=False, unique=True) birthday = models.DateField(null=False, blank=False) verified = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f'{self.first_name}: {self.email}'
2. 登录表单AuthForm的逻辑错误
你继承的AuthenticationForm默认基于username和password字段做验证,直接替换为email和password1后,完全破坏了内置的验证逻辑,且不需要添加Meta类指定模型(AuthenticationForm本身不依赖模型元数据)。
修复后的forms.py:
from django.contrib.auth.forms import AuthenticationForm from django import forms class AuthForm(AuthenticationForm): ''' Form that uses built-in AuthenticationForm to handle user auth ''' # 将默认的username字段改为邮箱输入类型 username = forms.EmailField(required=True, widget=forms.TextInput(attrs={ 'placeholder': 'Correo electrónico', 'name': 'email', 'type': 'email', 'class': 'form-control' })) password = forms.CharField(max_length=25, required=True, widget=forms.PasswordInput(attrs={ 'placeholder': 'Contraseña', 'name': 'password', 'type': 'password', 'class': 'form-control' }))
3. 视图中表单初始化的错误
AuthenticationForm的构造函数必须传入request对象作为第一个参数,你直接传request.POST会导致表单初始化失败,进而触发验证错误。
修复后的views.py:
from django.shortcuts import render, redirect, reverse from django.contrib.auth import authenticate, login from .forms import AuthForm def login_page(request): if request.method == 'POST': # 正确初始化AuthenticationForm子类:第一个参数为request,第二个为POST数据 form = AuthForm(request, data=request.POST) if form.is_valid(): # 从cleaned_data获取对应字段(这里username是用户输入的邮箱) email = form.cleaned_data.get('username') password = form.cleaned_data.get('password') user = authenticate(request, username=email, password=password) if user is not None: login(request, user) return redirect(reverse('network:profile')) # 验证失败时自动携带错误信息返回模板 return render(request, 'users/login.html', {'form': form}) return render(request, 'users/login.html', {'form': AuthForm()})
4. 模板字段引用的对应修改
因为表单字段名改为了username(实际是邮箱输入)和password,需要调整模板中的字段引用:
<form action="{% url 'users:login' %}" method="post"> {% csrf_token %} <div class="mb-3">{{ form.username }}</div> <div class="mb-3">{{ form.password }}</div> <div class="mb-3"><button class="btn btn-primary shadow d-block w-100" type="submit">Iniciar sesión</button></div> <p class="text-muted">Recuperar contraseña</p> </form>
内容的提问来源于stack exchange,提问作者Williams Jiménez
相关产品推荐
相关产品推荐

