为什么我的Django登录Form表单验证错误没有正常生效?
问题原因及最优方案
首先明确:表单验证失败时最优方案是直接渲染登录模板,不要重定向,重定向会丢失当前请求的表单错误上下文,无法展示具体错误。你遇到的不重定向就返回None的报错,是因为验证失败的分支没有正确返回HttpResponse对象,补全逻辑即可解决。
现有代码的两处核心问题
- views.py逻辑问题:POST验证失败后重定向,会销毁当前请求里携带错误信息的form实例;且如果去掉重定向后该分支无返回值,才会出现“未返回HttpResponse”的错误
- forms.py逻辑冗余问题:
authenticate返回None时已经说明用户名或密码错误,此时再调用user.check_password会触发空对象属性报错
修复步骤
1. 修正forms.py的clean方法
class LoginForm(forms.Form): username = forms.CharField(widget=forms.TextInput()) password = forms.CharField(widget=forms.PasswordInput()) remember_me = forms.BooleanField(required=False, label='Remember Me',help_text='Keep me logged in.',widget=forms.CheckboxInput()) def clean(self, *args, **kwargs): cleaned_data = super().clean(*args,**kwargs) username = cleaned_data.get("username") password = cleaned_data.get("password") if username and password: user = authenticate(username=username, password=password) if not user: raise forms.ValidationError("用户名或密码错误") if not user.is_active: raise forms.ValidationError("账号已被停用") return cleaned_data
这里去掉了冗余的check_password调用,因为authenticate已经内置了密码校验逻辑,返回None就说明账号密码不匹配。
2. 修正views.py的登录逻辑
def my_login(request): if 'next' in request.GET: messages.add_message(request, messages.WARNING, 'To Continue, Please login here!') if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): username = form.cleaned_data["username"] password = form.cleaned_data["password"] remember_me = form.cleaned_data['remember_me'] user = authenticate(username=username, password=password) if user: login(request, user) if not remember_me: request.session.set_expiry(0) else: request.session.set_expiry(1209600) return redirect('accounts:home') # 验证失败无需额外处理,直接走下方通用渲染逻辑即可 else: form = LoginForm() # 把渲染逻辑提到外层,GET请求、POST验证失败都会返回携带当前form实例的模板 return render(request, "login.html", {'form': form})
3. 模板中渲染具体错误信息
在login.html中可以按需展示全局错误或者字段级错误:
<!-- 展示clean方法抛出的全局验证错误 --> {% if form.non_field_errors %} <div class="error"> {% for error in form.non_field_errors %} <p>{{ error }}</p> {% endfor %} </div> {% endif %} <!-- 也可以在对应字段下方展示字段专属错误 --> <div class="form-group"> {{ form.username.label }} {{ form.username }} {% if form.username.errors %} <span class="error">{{ form.username.errors.0 }}</span> {% endif %} </div>
内容的提问来源于stack exchange,提问作者Shreyash mishra
相关产品推荐
相关产品推荐

