我需要为活动创建注册表单。每个注册的人都可以带来客人。我想在一页中注册所有内容。为此,我使用包含1 RegistrationForm
和X GuestForm
的视图。在我的模型中,我有一个Registration
和Guest
类我用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,
})
答案 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