You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:27:00