为什么我的Django表单没有触发ValidationError校验错误?
解决方案
1. 修正 forms.py 代码
Django 表单的跨字段校验建议使用标准的clean()方法,该方法会在你调用表单的is_valid()时自动触发,无需手动调用。同时你原有代码存在字段名引用错误的问题,修正后代码如下:
from django import forms from django.core.validators import MinValueValidator from django.utils.translation import gettext_lazy as _ class PlayerForm(forms.Form): # 积分上限 points_high = forms.IntegerField( validators=[MinValueValidator(0)], min_value=0, label='积分上限', required=False, widget=forms.NumberInput( attrs={'id': 'pointsHigh', 'class': "form-control"} ) ) # 积分下限 points_low = forms.IntegerField( validators=[MinValueValidator(0)], min_value=0, label='积分下限', required=False, widget=forms.NumberInput( attrs={'id': 'pointsLow', 'class': "form-control"} ) ) def clean(self): """跨字段校验上下限大小""" cleaned_data = super().clean() points_low = cleaned_data.get('points_low') points_high = cleaned_data.get('points_high') if points_low and points_high: if points_low > points_high: raise forms.ValidationError(_("下限值不能高于上限值!")) return cleaned_data
注意:原有代码中widget的name、href、value属性无需手动指定,Django会自动生成,冗余属性已删除
2. 修正 views.py 逻辑
原视图没有触发表单校验逻辑,直接从GET请求取参数查询,修正后逻辑为:先将请求参数传入表单,校验通过后再执行查询,校验失败则将错误信息返回前端:
def player_points(request): # 将GET参数传入表单 players_form = PlayerForm(request.GET) players = [] # 只有请求带参数且表单校验通过时才查询数据 if request.GET and players_form.is_valid(): points_high = players_form.cleaned_data['points_high'] points_low = players_form.cleaned_data['points_low'] stat_kwargs = {} if points_high: stat_kwargs['points__lte'] = points_high if points_low: stat_kwargs['points__gte'] = points_low players = Players.objects.filter(**stat_kwargs) context = { 'players': players, 'form': players_form } return render(request, 'nba/players.html', context)
注意:原有过滤条件的键需要是字符串格式,且要兼容参数为空的情况,避免无效过滤
3. 前端模板添加错误提示
在你的nba/players.html模板中,表单渲染位置添加如下代码,即可显示校验错误提示:
<!-- 显示跨字段校验错误 --> {% if form.non_field_errors %} <div class="alert alert-danger"> {% for error in form.non_field_errors %} <p>{{ error }}</p> {% endfor %} </div> {% endif %} <!-- 表单渲染示例 --> <form method="get"> {{ form.as_p }} <button type="submit" class="btn btn-primary">查询</button> </form>
内容的提问来源于stack exchange,提问作者nick_rinaldi
相关产品推荐
相关产品推荐

