Django提交可选表格

时间:2012-02-12 16:43:55

标签: django django-forms

我需要为活动创建注册表单。每个注册的人都可以带来客人。我想在一页中注册所有内容。为此,我使用包含1 RegistrationForm和X GuestForm的视图。在我的模型中,我有一个RegistrationGuest类我用ModelForm创建了两个表单。

问题是不需要填写GuestForm(您不必带来客人)。

def register_form(request):
  error = False
  if request.method == 'POST':
    register = RegistrationForm(request.POST, instance=Registration() )
    guests = [GuestForm(request.POST, prefix=str(x), instance=Guest()) for x in range(MAXGUESTS)]
    if register.is_valid():
        print("register is valid")

        for guest in guests:
            if guest.is_valid():
                print("guest is valid")
            else:
                print("guest is not valid") # always when empty form
                error = True
    else:
        print("register is not valid")
        error = True

    if not error:
       ... # save the form in the database

  register = RegistrationForm(instance=Registration())
  guests = [GuestForm(prefix=str(x), instance=Guest()) for x in range(MAXGUESTS)]
  return render_to_response('register.html',{
        'form': register,
        'max_guests': MAXGUESTS,
        'guests': guests,
        'error': error,
        })

所以我需要将一个表单设置为可选,并且能够在整个表单为空以及出现错误时进行区分。知道怎么样?

谢谢


解决方案

def register_form(request):
  GuestFormSet = modelformset_factory(Guest, exclude=('register',))
  error = False
  if request.method == 'POST':
    register = RegistrationForm(request.POST, instance=Registration() )
    guests = GuestFormSet(request.POST)
    if register.is_valid():
        print("register is valid")

        for guest in guests:
            if guest.is_valid():
                print("guest is valid") # even if some forms are empty
            else:
                print("guest is not valid")
                error = True
    else:
        print("register is not valid")
        error = True

    if not error:
       ... 
       # save the form in the database
       return something

  else:
      register = RegistrationForm(instance=Registration())
      guests = GuestFormSet(queryset=Guest.objects.none())
  return render_to_response('register.html',{
        'form': register,
        'max_guests': MAXGUESTS,
        'guests': guests,
        'error': error,
        })

4 个答案:

答案 0 :(得分:2)

您可以为来宾表单使用模型表单集。它可以区分空表格和无效表格。

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#model-formsets

答案 1 :(得分:0)

我想您需要一些方法来确定提交的客人表单是否实际填写。提交空表单时,请忽略它:

forms_to_save =[]

for form in guest_forms:
    if guest_form.is_valid()
        forms_to_save.append( form )
    else:
        if form.contains_data(): # you'll have to implement this
            error = True

if not error:
    for form in forms_to_save():
        form.save()

答案 2 :(得分:0)

我在构建婚礼RSVP应用程序时遇到类似问题。在我的情况下,每个访客都有一个'出席'复选框,如果没有选中(即访客没有参加),那么我不希望向用户报告任何错误。

我的客人模型(为简洁而精简):

class Guest(models.Model):
    email = models.EmailField(max_length=50, unique=True)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    attending = models.BooleanField(default=False)

我有一个名为RsvpForm的ModelForm类,它基于Guest模型创建一个表单。它看起来像这样:

class RsvpForm(ModelForm):
    class Meta:
        model = Guest
        fields = ('attending', 'email', 'first_name', 'last_name')

    def clean(self):
        cleaned_data = self.cleaned_data
        attending = cleaned_data.get('attending')

        if not attending:
            #clear the error collection
            self._errors['email'] = {}

        return cleaned_data

这个问题的解决方案在于我在RsvpForm类中重写的clean()方法。在其中,我检查客人是否参加。如果不是,那么我清除每个其他字段的错误消息。

最初,我已经清除了整个表单的错误:

if not attending:
    #clear the error collection
    self._errors['email'] = ''
    self._errors['first_name'] = ''
    self._errors['last_name'] = ''

但由于某些原因,修改任何这些密钥的值会导致表单验证失败,这反过来又阻止了Guest数据如果表明他们没有参加则会被保存。一个大多数人永远都找不到的小虫子,但仍然很烦人。

在某些方面,我还尝试通过在self._errors字典上调用.clear()来清除错误集合:

if not attending:
    #clear the error collection
    self._errors.clear()

但由于某种原因,即使我可以验证字典是空的,仍会显示错误。

最终结果是,如果选中“参加”复选框,则表单验证错误仅显示给我的用户,这是理想的,因为客人可能希望更新自己的联系信息,然后再决定他们将带来哪些加号之一。

答案 3 :(得分:0)

有一个比Alasdair更简单的解决方案:使用empty_permitted关键字参数。

>>> f = MyForm(data={}, empty_permitted=True)
>>> f.is_valid()
True