Django中required=True的ModelChoiceField未选中不触发校验错误问题
问题根因
你遇到的现象本质是浏览器原生表单校验拦截了提交请求,根本没有发往后端,具体原因有两个:
- Django给
required=True的ModelChoiceField渲染的HTML input标签会自动带上required属性,浏览器提交表单时会优先执行原生校验,要求该单选字段必须有选中值 - 你的CSS代码把radio input设置为
visibility: hidden,浏览器触发必填校验后的默认错误气泡无法正常显示,你感知不到校验失败,只会觉得点击提交无响应。因为请求始终没有发往后端,后端收到的还是GET请求,if request.method == 'POST'自然返回False,也不会触发Django后端的表单校验逻辑。
可直接使用的解决方案
以下三个方案任选其一即可:
方案1:关闭浏览器原生校验,交给Django后端处理
在模板的form标签上添加novalidate属性,完全关闭当前表单的浏览器原生校验逻辑,请求会正常提交到后端,Django的表单校验会抛出必填错误,模板中{{ form.errors }}就能正常渲染错误提示。
修改后的form标签代码:
<form action="/raisepoller/" method="post" novalidate> <!-- 其余内容不变 --> </form>
方案2:移除HTML标签上的required属性,保留后端校验逻辑
只删除渲染到前端input上的required属性,字段本身的必填校验仍由Django后端处理,修改表单代码如下:
class PollersForm(forms.Form): poller_category = forms.ModelChoiceField(widget=forms.RadioSelect(attrs={ 'class': 'poller-category-radio', 'required': False # 仅移除HTML标签上的required属性,不影响后端校验 }), queryset=Category.objects.all().order_by('category'), label='Select a Category', required=True)
方案3:自定义前端校验提示
如果需要保留浏览器原生校验能力,可添加JS监听表单的invalid事件,自定义错误提示样式,替代浏览器默认的气泡提示,适配你隐藏的单选框样式。
额外注意事项
你视图中redirect的写法存在问题,已经拼好完整路径的情况下不需要额外传递request和id参数,修改为:
return redirect(poller_url)
内容的提问来源于stack exchange,提问作者JSRB
相关产品推荐
相关产品推荐

