我正在学习使用Django 1.4(我会在1.7发布后立即进行升级)。
我有一个测试表单,其中我已将所有字段标记为required = False,但我需要让用户在表单上输入至少一个字段。只要输入至少一个条目,输入哪个字段无关紧要。
我确实有一个可行的解决方案,但我认为这可以做得更好,所以我希望有一个对django更好理解的人可以向我展示更好的解决方案。
这是我的型号代码:
....
nationality_visa_country_of_birth = models.TextField(null=True, blank=True)
nationality_visa_citizenship = models.TextField(null=True, blank=True)
nationality_visa_residency = models.TextField(null=True, blank=True)
nationality_visa_work_visa = models.TextField(null=True, blank=True)
nationality_visa_study_visa = models.TextField(null=True, blank=True)
nationality_visa_specialist_visa = models.TextField(null=True, blank=True)
nationality_visa_other_visa = models.TextField(null=True, blank=True)
nationality_visa_current_valid_passport_display_type = models.PositiveIntegerField(default=0)
nationality_visa_multiple_passports = models.BooleanField(default=False)
nationality_visa_passport_nationality = models.TextField(null=True, blank=True)
nationality_visa_timestamp_added = models.DateTimeField(auto_now_add=True, auto_now=False)
nationality_visa_timestamp_updated = models.DateTimeField(auto_now=True, auto_now_add=False)
....
这是我的表单代码:
nationality_visa_country_of_birth = forms.CharField(label=_('Country of Birth'), max_length=250, required=False)
nationality_visa_citizenship = forms.CharField(label=_('Citizenship'), max_length=250, required=False)
nationality_visa_residency = forms.CharField( label=_('Residency'), max_length=250, required=False)
nationality_visa_work_visa = forms.CharField( label=_('Work Visa'), max_length=250, required=False)
nationality_visa_study_visa = forms.CharField( label=_('Student Visa'),max_length=250, required=False)
nationality_visa_specialist_visa = forms.CharField(label=_('Specialist Visa'), max_length=250, required=False)
nationality_visa_other_visa = forms.CharField(label=_('Other Visa'), max_length=250, required=False)
nationality_visa_current_valid_passport_display_type = forms.TypedChoiceField(coerce=int, label=_('Current Valid Passport'), choices=[(x, x) for x in range(0, 3)], required=False)
nationality_visa_multiple_passports = forms.BooleanField( label=_('Multiple Passports'), required=False, help_text=_("Select this option if you're going to enter multiple passport details into the field below."))
nationality_visa_passport_nationality = forms.CharField( label=_('Nationality of Passport(s)'), max_length=250, required=False)
以下是forms.py上的验证数据,它确实要求用户输入至少一个字段:
def clean(self):
cd_nvdf = super(NationalityVisaDetailsForm, self).clean()
if 'nationality_visa_country_of_birth' in cd_nvdf and len(cd_nvdf['nationality_visa_country_of_birth'].strip()) == 0:
if 'nationality_visa_citizenship' in cd_nvdf and len(cd_nvdf['nationality_visa_citizenship'].strip()) == 0:
if 'nationality_visa_residency' in cd_nvdf and len(cd_nvdf['nationality_visa_residency'].strip()) == 0:
if 'nationality_visa_work_visa' in cd_nvdf and len(cd_nvdf['nationality_visa_work_visa'].strip()) == 0:
if 'nationality_visa_study_visa' in cd_nvdf and len(cd_nvdf['nationality_visa_study_visa'].strip()) == 0:
if 'nationality_visa_specialist_visa' in cd_nvdf and len(cd_nvdf['nationality_visa_specialist_visa'].strip()) == 0:
if 'nationality_visa_other_visa' in cd_nvdf and len(cd_nvdf['nationality_visa_other_visa'].strip()) == 0:
if 'nationality_visa_current_valid_passport_display_type' in cd_nvdf and cd_nvdf['nationality_visa_current_valid_passport_display_type'] == 0:
if 'nationality_visa_passport_nationality' in cd_nvdf and len(cd_nvdf['nationality_visa_passport_nationality'].strip()) == 0:
self._errors['nationality_visa_country_of_birth'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_citizenship'] = self.error_class([_(" ")])
self._errors['nationality_visa_residency'] = self.error_class([_(" ")])
self._errors['nationality_visa_work_visa'] = self.error_class([_(" ")])
self._errors['nationality_visa_study_visa'] = self.error_class([_(" ")])
self._errors['nationality_visa_specialist_visa'] = self.error_class([_(" ")])
self._errors['nationality_visa_other_visa'] = self.error_class([_(" ")])
self._errors['nationality_visa_current_valid_passport_display_type'] = self.error_class([_(" ")])
self._errors['nationality_visa_passport_nationality'] = self.error_class([_(" ")])
del self.cleaned_data['nationality_visa_country_of_birth']
del self.cleaned_data['nationality_visa_citizenship']
del self.cleaned_data['nationality_visa_residency']
del self.cleaned_data['nationality_visa_work_visa']
del self.cleaned_data['nationality_visa_study_visa']
del self.cleaned_data['nationality_visa_specialist_visa']
del self.cleaned_data['nationality_visa_other_visa']
del self.cleaned_data['nationality_visa_current_valid_passport_display_type']
del self.cleaned_data['nationality_visa_passport_nationality']
return cd_nvdf
目前,经过验证的表单突出显示了上述表单字段,但对于模板上的每个表单字段,以下html代码都插入到html代码中,因此在每个表单字段下都有一个额外的换行符:
<span class="help-inline">
<strong>
<br>
</strong>
</span>
如何更好地编写验证码,以便用户输入至少一个表单字段和/或不包含上面显示的额外换行符?
答案 0 :(得分:1)
这是工作解决方案:
def clean(self):
cd_nvdf = super(NationalityVisaDetailsForm, self).clean()
if not any(
cd_nvdf.get(x, '')
for x in (
'nationality_visa_country_of_birth',
'nationality_visa_citizenship',
'nationality_visa_residency',
'nationality_visa_work_visa',
'nationality_visa_study_visa',
'nationality_visa_specialist_visa',
'nationality_visa_other_visa',
'nationality_visa_current_valid_passport_display_type',
'nationality_visa_passport_nationality',
)
):
self._errors['nationality_visa_country_of_birth'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_citizenship'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_residency'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_work_visa'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_study_visa'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_specialist_visa'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_other_visa'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_current_valid_passport_display_type'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
self._errors['nationality_visa_passport_nationality'] = self.error_class([_("You must enter at least one Nationality & Visa Detail.")])
return cd_nvdf
我希望这会对某人有所帮助。
答案 1 :(得分:0)
可能有一些Django细节可以帮到你,但我建议先考虑Python。
对于第一项任务,我认为你可能会受益于filter
。
首先,我们需要您要检查的值列表:
values_we_care_about = ['nationality_visa_country_of_birth'
'nationality_visa_citizenship'
'nationality_visa_residency'
'nationality_visa_work_visa',
etc.]
接下来,我们需要提炼出你用来将东西检查成一个简单函数的逻辑
def checking_stuff_function(value_cared_about):
return value_cared_about in cd_nvdf and cd_nvdf.get(value_cared_about, None)
现在,我们可以使用此功能并使用它来过滤所有值(如果你在Python2上,这将立即返回一个列表,但是如果你&#39;在Python3上,你将得到一个生成器;我将假设Python2):
checked_values = filter(checking_stuff_function, values_we_care_about)
现在,我们可以查看有多少checked_values
完成了这项工作。你可能已经看到了这种情况......
if len(checked_values) < 1:
# There's an error!
现在,您只需要重置表单(因为之前我们使用了过滤器,为什么不在这里使用map
?):
map(lambda val: del self.cleaned_data[val], values_we_care_about]
但是,我从来没有用表格做过。是否真的有必要在重写的清理方法上删除它们?在视图中可以更好地处理这个问题吗?我会把这个留给其他人来回答。
之后你可以退回你的表格。
修改强>
我忘记了你的错误。这也可以通过类似于我们在此处完成的方式完成,因此我不会尝试拼写出来。
您原来的代码缺失的原因是DRY原则:不要重复自己。&#39;尝试在您正在做的事情中找到常见模式,并将这些模式用于您的优势。如果你在三到四个地方写了相同的字符串数组,这就是一个问题。将它们保存到列表中,然后迭代它们。要阅读的代码要少得多。