除非选中,否则使用BooleanField的Django表单总是无效的

我有一个使用以下forms的应用程序:

class ConfirmForm(forms.Form): account_name = forms.CharField(widget=forms.HiddenInput) up_to_date = forms.BooleanField(initial=True) 

我使用下面的模板exerpt中的表单:

 <form class="confirmform" action="/foo/" enctype="multipart/form-data" method="post"> {{ confirm_form.up_to_date }} Check if this data brings the account up to date.<br> {{ confirm_form.account_name }} <input type="submit" name="confirm" value="Confirm" /> </form> 

我的看法使用以下基本的代码结构:

 if request.method == 'POST': #check for 'confirm' because I actually have multiple forms in this page if 'confirm' in request.POST: confirm_form = ConfirmForm(request.POST) if confirm_form.is_valid(): #do stuff else: c['confirm_form'] = confirm_form else: c['confirm_form'] = ConfirmForm({'account_name':'provided_value'}) 

有两件事是错误的:

1)即使我有初始=真,checkbox未加载页面加载时

2)除非我检查checkbox,否则表格总是无效的。 它仅给up_to_date提供错误:“此字段是必需的。”

我已经阅读了这个类似的问题,但他的解决scheme不适用于我的项目。

发生什么了?

编辑:

我更新了上面的代码,以更忠实于我的实际代码。

问题#1是我的错,因为当表单被实例化时,我通过绑定数据覆盖了初始值。

问题2我仍然在考虑一个问题。 在up_to_date上使用required=False可以解决问题,但是使用默认的小部件似乎不正确,但是BooleanField可以是NULL (导致有效性检查失败),也可以是True但不会是False

initial=True应该使用checked="checked"来呈现小部件,所以我没有看到那里的问题..但是表单无效的原因是因为所有的字段都是默认情况下需要的,除非您另外指定。

Field.required¶默认情况下,每个Field类都假定这个值是必需的,所以如果你传递一个空的值 – None或者空string(“”) – 那么clean()会引发一个ValidationErrorexception:

如果您希望checkbox或任何其他值是可选的,则需要将required=False传递到表单字段构造函数中。

 up_to_date = forms.BooleanField(initial=True, required=False) # no longer required.. 

在Django窗体中,必须使用required=False创build布尔字段。

当checkbox未选中时,浏览器不会在请求的POST参数中发送字段。 没有指定该字段是可选的,当不在POST参数中时,Django会将其视为缺失字段。

Imho这将是很好的Django具有默认情况下布尔表单域的这种行为..

(Yuji的评论已经回答了这个问题,但作为答案是有用的)

根据官方文件 :

如果你想在你的表单中包含一个可以是TrueFalse的布尔值(例如checked或unchecked checkbox),你必须记住在创buildBooleanField时必须传入required=False

确保在第一次加载页面时不会覆盖初始表单。

我原来并没有检查request.GET中是否有任何实际的东西。 第一次页面加载request.GET是无,并调用SomeForm(request.GET)实际上会消除初始值。

 def some_view(request): form = SomeForm() if request.method == 'GET': form = SomeForm(request.GET) 

添加一个检查,以确保有request.GET中解决这个问题。

 def some_view(request): form = SomeForm() if request.method == 'GET' and request.GET: form = SomeForm(request.GET)