【问题标题】:Django form with just a BooleanField只有一个 BooleanField 的 Django 表单
【发布时间】:2010-12-05 23:08:52
【问题描述】:

我对 Django 比较陌生,我正在使用 Django 1.0。 我有这个:
forms.py:

class MyForm(forms.Form):
    extra_cheeze = forms.BooleanField(required=False,
                                      initial=False,
                                      label='Extra cheeze')

views.py:

def order_something(request):
    form = MyForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        # do stuff...

问题是除非选中复选框,否则表单无效,因此似乎没有办法从字段中获取 False 值。 据我从the docs 了解到,它应该可以工作。如果我将 CharField 添加到我的表单中,它会起作用...

我在这里误解了什么还是这是一个错误? (是的,我用谷歌搜索过,但没有发现任何相关内容)

更新:按照@Dominic Rodger 的建议,我尝试添加一个隐藏字段
dummy = forms.CharField(initial='dummy', widget=forms.widgets.HiddenInput())
这使得表格有效。这种解决方法使我现在可以继续前进,但如果我误解了某些东西,我仍然会很有趣......

【问题讨论】:

  • 嗯。对我来说听起来像是一个错误。您可以使用隐藏字段解决它吗?
  • 有一些错误报告听起来有点相似 - 请参阅 google.co.uk/search?q=django+checkbox+forms+bug
  • 我会试试的。我怀疑表单不喜欢空数据,因为浏览器不会包含未选中复选框的字段。
  • 我会将此作为 Django 中的错误提交,因为我看不出任何正当理由说明我建议的更改会修复它。见docs.djangoproject.com/en/dev/internals/contributing/#id1
  • 使用 django 1.0.2 和 FF 3.0.14 和 IE7,它适用于我,没有解决方法(但我在表单 html 中添加了一个提交按钮)。您使用的是哪个版本的 django 和浏览器?您是使用带有提交按钮的 html 表单,还是使用 ajax 来提交表单?

标签: django django-forms


【解决方案1】:

这不是答案,它仅描述了 Django 行为。

Python 3.8.4rc1 上的 Django 3.0.7,Debian 10/testing。

我的场景是 html <form> 有更多的 django forms.Form 在里面呈现类,其中一个只有 BooleanField。 (页面中还有其他小<forms> 类似搜索表单)。

class OrderInvoiceTypeForm(forms.Form):
    is_business = forms.BooleanField(label="business", initial=False)  # with or without required=False

我通过提交按钮提交,该按钮不在 OrderInvoiceTypeForm 中,而是在 html 中。

使用 required=False 表单始终有效,并且 is_business 键位于 .cleaned_data 中。

不需要(或带有=True):

检查:

form_with_boolean.is_valid()    # True
form_with_boolean.cleaned_data  # {'is_business': True}

未选中:

form_with_boolean.is_valid()    # False
form_with_boolean.cleaned_data  # {}

在开发工具的第二种情况下,我可以看到浏览器 (Chrome) 没有发送 is_business 值 POST 变量。添加隐藏字段将无济于事。

【讨论】:

    【解决方案2】:

    我的问题中的代码存在错误。感谢@d0ugal 通过包含一个稍微不同的示例帮助我发现它。问题出在这里:

    form = MyForm(request.POST or None) # <- PROBLEM HERE!!!!!!!!!!!!!!!!
    if request.method == 'POST' and form.is_valid():
        # do stuff...
    

    错误是我假设 request.POST 如果它是一个帖子,它将评估为 True。但是由于浏览器不会为未选中的复选框发布任何内容,并且这是唯一的字段,因此 POST 数据是一个空字典,其计算结果为 False。这导致 None 被用作初始化数据,导致表单未绑定且无效。
    @d0ugal 的例子是安全的,首先测试 request.method。

    【讨论】:

      【解决方案3】:

      这也适用于 1.1、1.0.3 和 1.0(我设置了这三个虚拟环境)。我只在 FireFox 中对此进行了测试,所以如果它是浏览器问题,那是另一回事,但据我所知,它们都使用相同的复选框处理 POST 数据。

      这里是该项目的完整代码,您可以在闲暇时重现并与您的代码进行比较以查看差异。

      在 Ubuntu 中设置

      $ django-admin.py startproject testing
      $ cd testing/
      $ python manage.py startapp myfirst
      

      然后在myfirst app文件夹中;

      /myfirst/views.py

      from django.shortcuts import render_to_response
      
      from myfirst.forms import MyForm
      
      def testing(request):
          if request.method == 'POST':
              form = MyForm(request.POST)
              if form.is_valid():
                  result = "valid"
              else:
                  result = "not valid"
          else:
              form = MyForm()
              result = "no post"
      
          return render_to_response('test.html', {'form':form, 'result':result,})
      

      /myfirst/forms.py 从 django 导入表单

      class MyForm(forms.Form):
          extra_cheeze = forms.BooleanField(required=False,initial=False,label='Extra cheeze')
      

      /myfirst/templates/test.html

      <html>
      <head>
      </head>
      <body>
          <form action="." method="POST">
              {{ form }}
              <input type="submit" value="test">
          </form>
          {{ result }}
      </body>
      </html>
      

      /urls.py 从 django.conf.urls.defaults 导入 *

      from myfirst.views import testing
      
      urlpatterns = patterns('',
           (r'.*', testing),
      )
      

      然后只需运行项目 $ python manage.py runserver 并浏览到http://localhost:8000/。您实际上会发现 required 对复选框没有任何作用,因为您不能将其留空 - “空白”答案实际上是“否”。如果您想确保用户选择一个答案,则有多个选择,用户必须选择是或否。你也可以强迫他们用单选按钮回答。

      【讨论】:

      • 其实'required'的默认值是True,见docs.djangoproject.com/en/dev/ref/forms/fields/#required。但是你的回答让我发现了我的错误,所以+1!我会回答我自己的问题,让未来的读者清楚问题是什么......
      • 我从未说过 required 的默认值是 True 或 False :) 我只是说它没有什么不同,因为它不可能将复选框“空白”保留为选中或未选中。所以,总有一个价值——被要求或不被要求不会有所作为。
      猜你喜欢
      • 2014-05-21
      • 2010-11-30
      • 1970-01-01
      • 2015-09-28
      • 2014-03-24
      • 2021-06-07
      • 2012-04-03
      • 2010-10-25
      • 2012-01-22
      相关资源
      最近更新 更多