我有一个使用以下形式的应用程序:
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)即使我有initial = True,当页面加载
时,也会取消选中该复选框2)除非选中复选框,否则表格始终无效。它仅为up_to_date提供错误:“此字段是必需的。”
我已阅读this similar question,但他的解决方案不适用于我的项目。
那么......发生了什么事?
修改
我更新了上面的代码,以便更忠实于我的实际代码。
问题#1是我的错,因为我在实例化表单时通过绑定数据来覆盖初始值。
问题#2我仍然考虑一个问题。在required=False
上使用up_to_date
可以解决问题,但是使用默认小部件似乎不正确,BooleanField
可以是NULL
(导致有效性检查失败) )或True
但从不False
。
答案 0 :(得分:35)
initial=True
应该使用checked="checked"
呈现窗口小部件,因此我没有看到问题..但窗体无效的原因是默认情况下所有字段都是必需的,除非您另行指定。
Field.required¶默认情况下,每个Field类都假设值为 必需的,所以如果你传递一个空值 - 无或空 string(“”) - 然后clean()将引发ValidationError异常:
如果您希望复选框或任何其他值是可选的,则需要将required=False
传递到表单字段构造函数中。
up_to_date = forms.BooleanField(initial=True, required=False)
# no longer required..
答案 1 :(得分:30)
在Django表单中,必须使用required=False
创建布尔字段。
如果未选中该复选框,则浏览器不会在请求的POST参数中发送该字段。如果没有指定该字段是可选的,Django会在不在POST参数中时将其视为缺少的字段。
Imho,对于布尔表单字段,Django默认具有此行为会很好..
(Yuji在评论中已经回答了这个问题,但它可以作为答案)
答案 2 :(得分:12)
如果您希望在表单中包含可以是
True
或False
的布尔值(例如选中或未选中复选框),则必须记住传入 {{1} 时创建BooleanField。
答案 3 :(得分:0)
确保在第一次加载页面时不覆盖初始表单。
我最初没有检查请求中是否有任何内容.GET。页面第一次加载request.GET为None,调用SomeForm(request.GET)实际上会清除初始值。
def some_view(request):
form = SomeForm()
if request.method == 'GET':
form = SomeForm(request.GET)
添加支票以确保请求中有内容.GET已修复此问题。
def some_view(request):
form = SomeForm()
if request.method == 'GET' and request.GET:
form = SomeForm(request.GET)
答案 4 :(得分:0)
如果按照建议进行操作,则您的 up_to_date 字段可能始终为False。而且您永远不会知道这是因为用户还是想要这样,因为用户跳过了该字段!
我在法律上要求使用OPT_IN问题时也遇到了同样的问题。在哪里进行注册,我需要让用户做出良心决定,以允许我的系统向其发送未经请求的电子邮件(或不向他们发送)。我正在使用Django-Allauth和自定义用户数据库。
我将在下面分享我的解决方案,希望您可以适应您的情况-我改编自the DOCS。
forms.py:
# ExtraFieldsSignup as per https://stackoverflow.com/a/12308807
class SignupFormExtraFields(forms.Form):
CHOICES = (('1', 'YES, keep in touch',), ('2', 'No',))
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')
opt_in = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
# Now we figure out what the user chose:
if self.cleaned_data['opt_in'] == '1':
user.opt_in = True
else:
user.opt_in = False
user.save()
答案 5 :(得分:0)
只是预感,但这可能只是基本知识-花费了几个小时才意识到与基本变量类型类似的东西。
就我而言,创建表格后(非常基本,请参见下文)
class para_selection(forms.Form):
first=forms.BooleanField(initial=False, required=False)
second=forms.BooleanField(initial=False, required=False)
third=forms.BooleanField(initial=False, required=False)
fourth=forms.BooleanField(initial=False, required=False)
...我正在使用 如果选择=='真': .. 在我看来。但是由于表单使用的是布尔值,因此正确的代码应为: 如果选择为True:
第一行将永远无法工作,因为布尔型不使用“ ==”。希望情况并非如此,但由于我一直在Internet上进行尝试和搜索,而不关注我使用的变量类型,因此想在这里进行标记。