除非选中,否则带有BooleanField的Django表单始终无效

dho*_*and 46 django django-forms

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

class ConfirmForm(forms.Form):
    account_name = forms.CharField(widget=forms.HiddenInput)
    up_to_date = forms.BooleanField(initial=True)
Run Code Online (Sandbox Code Playgroud)

我使用以下模板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>
Run Code Online (Sandbox Code Playgroud)

我的视图使用以下基本代码结构:

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'})
Run Code Online (Sandbox Code Playgroud)

有两件事是错的:

1)即使我有initial = True,当页面加载时取消选中该复选框

2)除非我勾选复选框,否则表格始终无效.它仅为up_to_date提供错误:"此字段是必需的."

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

发生什么了?

编辑:

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

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

问题#2我仍然考虑一个问题.使用required=Falseon up_to_date将解决问题,但是使用默认小部件似乎不正确,a BooleanField可以NULL(导致有效性检查失败)或者True从不False.

Yuj*_*ita 38

initial=True应该渲染窗口小部件,checked="checked"所以我没有看到问题..但窗体无效的原因是因为默认情况下所有字段都是必需的,除非你另有说明.

Field.required默认情况下,每个Field类都假定该值是必需的,因此如果传递一个空值 - None或空字符串("") - 那么clean()将引发ValidationError异常:

如果您希望复选框或任何其他值是可选的,则需要传入required=False表单字段构造函数.

up_to_date = forms.BooleanField(initial=True, required=False) 
# no longer required..
Run Code Online (Sandbox Code Playgroud)

  • 尽管如此,initial = True没有效果.另外,为什么解决方案是使该字段可选?BooleanField不能返回false吗? (6认同)
  • 至于为何选择该字段?1:文档说的是这样.但是2:复选框是HTML元素,在"未选中"时不提交数据."假"值只能通过缺少输入来确定. (2认同)
  • Yuji:(1)他们呢?[BooleanField的文档](https://docs.djangoproject.com/en/dev/ref/models/fields/#booleanfield)说没有这样的事情.(2)完全正确!我现在明白了我需要做些什么来使它工作,但我不知道为什么设计师会在我们想要一个错误的结果时允许is_valid()失败.可能是文档应该告诉我们总是让'required = False'除非更改小部件或验证器. (2认同)

yai*_*chu 32

在Django表单中,必须使用创建布尔字段required=False.

如果未选中该复选框,则浏览器不会在请求的POST参数中发送该字段.如果没有指定字段是可选的,Django会在不在POST参数中时将其视为缺少字段.

Imho,对于布尔表单字段,Django默认具有此行为会很好.

(在Yuji的评论中已经回答了这个问题,但它可以作为答案)


use*_*ser 13

根据官方文件:

如果要在表单中包含可以是True或者False(例如,选中或未选中复选框)的布尔值,则必须记住在required=False创建BooleanField时传入.