Django Formset中的必填字段和可选字段

时间:2014-12-13 00:58:13

标签: python django forms formset

我创建了一个formset来复制两个输入字段,名字和姓氏。我想制作第一套"第一名"和"姓氏"第二个时需要的字段,第三个设置为可选字段。换句话说,必须填写三组输入框中的至少一个。有没有办法做到这一点?我是否必须制作2个单独的表格/表格以适应这种情况?

我的问题的原因是我想拥有3套名字和姓氏字段。如果用户只填写3组中的一组并单击提交,Django将抛出键错误,因为其他2组未填写。

forms.py

from django import forms


class NameForm (forms.Form):

    first_name = forms.CharField (max_length = 20, required = False)
    last_name = forms.CharField (max_length = 20, required = False)

views.py

from django.shortcuts import render
from django.forms.formsets import formset_factory
from nameform.forms import NameForm
from nameform.addName import webform


# Create your views here.
def addname (request):
    NameFormSet = formset_factory (NameForm, extra = 2, max_num = 5)    # Set maximum to avoid default of 1000 forms.
    if request.method == 'POST':
        # Django will become valid even if an empty form is submitted. Adding initial data causes unbound form and
        # trigger formset.errors
        formset = NameFormSet (request.POST, initial = [{'first_name': 'John', 'last_name': 'Doe'}])

        if formset.is_valid ():
            location = request.POST ['site']
            data = formset.cleaned_data

            for form in data:
                firstname = form ['first_name']
                lastname = form ['last_name']

                webform (firstname, lastname, location)

            context = {'data': data, 'location': location}

            return render (request, 'nameform/success.html', context)

    else:
        formset = NameFormSet ()

    return render (request, 'nameform/addname.html', {'formset': formset})

以下是我尝试过的步骤:

  1. 如果我删除了" required = False",则会使formset中的每个表单都需要。如果用户仅填写第一组并将第二组留空,则会标记KeyError。
  2. 如果用户提交了空白表单,则将此formset设置为上面的可选项也将引发KeyError。
  3. Add Name Form

    KeyError - firstname = form ['first_name'

2 个答案:

答案 0 :(得分:0)

在这种情况下,Django formset以一种特殊的方式工作 - 没有数据的表单空cleaned_data但被视为有效。因此,您必须手动检查表单数据的存在:

# at imports section of views.py
from django.forms.util import ErrorList

# at addname()
actual_data = []
for form in data:
    firstname = form.get('first_name')
    lastname = form.get('last_name')
    if firstname and lastname:
        webform (firstname, lastname, location)
        actual_data.append(form)
if actual_data:
    context = {'data': actual_data, 'location': location}
    return render(request, 'nameform/success.html', context)
formset._non_form_errors = ErrorList(['Enter at least one person name.'])

答案 1 :(得分:0)

你需要从BaseFormSet继承并覆盖" clean"实现手动验证的方法。

django docs有一个例子:https://docs.djangoproject.com/en/1.7/topics/forms/formsets/#custom-formset-validation