以下代码应显示 formset ,其中包含一定数量的 TravellerForm ,然后验证它们并保存 CompleteSubscription 和他的旅行者相关。
只有主要联系人 - 第一个表格 - 应该有一个由正则表达式验证的E.164格式的电话号码。
它正确地取消了第一个以外的其他表单的电话号码字段,并且正确显示了我需要的字段。
然后,当我提交表单时,旅行者会保存在我的数据库中,包括第一个,但我在其中放入了无效的电话号码。订阅已正确保存。
为了解决这个问题,我已经覆盖了clean_phone_number方法,它看起来很有效,但它给了我两个错误而不仅仅是一个错误。
为什么我需要覆盖clean_phone_number方法来显示错误,是不是应该在保存之前调用其表单的clean方法的formset?
如果是这样,为什么我覆盖它时调用了clean_phone_number方法?
我很有意思地知道当我实际输入12个字符时django如何计算143个字符(我想删除一个字段可能会破坏一些计数)。
有模板,
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
</br>
{% endfor %}
<input type="submit" value="Valider" />
</form>
观点,
def set_main_form(formset):
is_main = True
for form in formset:
if is_main:
is_main = False
else:
del form.fields['phone_number']
# Main contact is the first Travelller
def complete_subscription_create(request, base_pk):
base = BaseSubscription.objects.get(pk=base_pk)
number_forms = base.nb_adults + base.nb_children + base.nb_babies
TravellerFormSet = modelformset_factory(Traveller, form=TravellerForm,
extra=number_forms)
if request.method == 'POST':
formset = TravellerFormSet(request.POST, request.FILES)
set_main_form(formset)
if formset.is_valid():
base = BaseSubscription.objects.get(pk=base_pk)
subscription = CompleteSubscription(base_subscription=base)
subscription.save()
formset[0].instance.is_main_contact = True
for form in formset:
form.instance.subscription = subscription
formset.save()
return redirect('home')
else:
formset = TravellerFormSet()
set_main_form(formset)
return render(request, 'offerspace/completesubscription_form.html',
{'formset': formset})
表单中实例化的表单
class TravellerForm(forms.ModelForm):
class Meta:
model = Traveller
fields = ('first_name', 'second_name', 'last_name',
'passport_country', 'phone_number')
# For some reasons, the regex validator works when I uncomment this
#def clean_phone_number(self):
#cleaned_data = super(TravellerForm, self).clean()
#return cleaned_data
TravellerForm的模型
class Traveller(models.Model):
first_name = models.CharField(max_length=128)
second_name = models.CharField(max_length=128, blank=True)
last_name = models.CharField(max_length=128)
# This field is in E.164 Format, see https://en.wikipedia.org/wiki/E.164
# for more informations about this format
phone_error_message = """
Phone number must be in E.164 format.
Ex: +33123456789
"""
phone_regex = RegexValidator(regex=r'^\+?1?\d{8,15}$',
message=phone_error_message,
code='invalid_phone_number')
phone_number = models.CharField(validators=[phone_regex], blank=True,
max_length=16)
passport_country = models.ForeignKey(Country)
is_main_contact = models.BooleanField(default=False)
subscription = models.ForeignKey(CompleteSubscription)
在视图中实现了CompleteSubscription模型,
class CompleteSubscription(models.Model):
base_subscription = models.OneToOneField(BaseSubscription)
final_price = models.PositiveIntegerField(default=0)