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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:45:03