Я нашел ответ, который звучит примерно так (да, я знаю, что это глупо!)
def new_client_view(request):
if request.method == 'POST':
formDetails = ClientDetailsForm(request.POST)
formAddress = ClientAddressForm(request.POST)
formHomePhone = ClientPhoneForm(request.POST)
if formDetails.is_valid() and formAddress.is_valid() and formHomePhone.is_valid():
c = Client()
c.save()
fd = formDetails.save(commit=False)
fd.client = c
fd.created_by = request.user
fd.save()
fa = formAddress.save(commit=False)
fa.client = c
fa.created_by = request.user
fa.save()
fph = formHomePhone.save(commit=False)
fph.client = c
fph.created_by = request.user
fph.save()
if 'p2-number' in request.POST and request.POST['p2-number']:
formWorkPhone = ClientOtherPhoneForm(request.POST)
fpw = formWorkPhone.save(commit=False)
fpw.client = c.id
fpw.created_by = request.user
# if the work number is valid
if fpw.is_valid():
# check the mobile number before you save the work number
if 'p3-number' in request.POST and request.POST['p3-number']:
formMobilePhone = ClientOtherPhoneForm(request.POST)
fpm = formMobilePhone.save(commit=False)
fpm.client = c
fpm.created_by = request.user
# if the mobile number is good then there is no more checking to do
if fpm.is_valid():
fpm.save()
# else load up the form again with the error for the mobile phone and the original
# data for the mobile phone and the work phone
else:
formWorkPhone = ClientOtherPhoneForm(request.POST)
return render_to_response('client/new_client.html', {'formDetails': formDetails, 'formAddress': formAddress, 'formHomePhone': formHomePhone, 'formWorkPhone': formWorkPhone, 'formMobilePhone': formMobilePhone}, context_instance=RequestContext(request))
# if the work number is valid and the mobile field wasn't used then just save the work number
fpw.save()
# if the work number is not valid then find out if a mobile number
# was entered and feed it back to the form
else:
if 'p3-number' in request.POST and request.POST['p3-number']:
formMobilePhone = ClientOtherPhoneForm(request.POST)
else:
formMobilePhone = ClientPhoneForm(initial={'phone_type':'mobi'}, prefix="p3")
return render_to_response('client/new_client.html', {'formDetails': formDetails, 'formAddress': formAddress, 'formHomePhone': formHomePhone, 'formWorkPhone': formWorkPhone, 'formMobilePhone': formMobilePhone}, context_instance=RequestContext(request))
return render_to_response('client/client.html', context_instance=RequestContext(request))
# if the form doesn't validate then you need to find out if the optional fields contain data,
# and if so load that data back into the form
else:
if 'p2-number' in request.POST and request.POST['p2-number']:
formWorkPhone = ClientOtherPhoneForm(request.POST, prefix="p2")
else:
formWorkPhone = ClientPhoneForm(initial={'phone_type':'work'}, prefix="p2")
if 'p3-number' in request.POST and request.POST['p3-number']:
formMobilePhone = ClientOtherPhoneForm(request.POST, prefix="p3")
else:
formMobilePhone = ClientPhoneForm(initial={'phone_type':'mobi'}, prefix="p3")
return render_to_response('client/new_client.html', {'formDetails': formDetails, 'formAddress': formAddress, 'formHomePhone': formHomePhone, 'formWorkPhone': formWorkPhone, 'formMobilePhone': formMobilePhone}, context_instance=RequestContext(request))
else:
formAddress = ClientAddressForm()
formDetails = ClientDetailsForm()
formHomePhone = ClientPhoneForm(initial={'phone_type':'home'}, prefix="p1")
formWorkPhone = ClientPhoneForm(initial={'phone_type':'work'}, prefix="p2")
formMobilePhone = ClientPhoneForm(initial={'phone_type':'mobi'}, prefix="p3")
return render_to_response('client/new_client.html', {'formDetails': formDetails, 'formAddress': formAddress, 'formHomePhone': formHomePhone, 'formWorkPhone': formWorkPhone, 'formMobilePhone': formMobilePhone}, context_instance=RequestContext(request))
Я думаю, что мне нужно переписать функцию is_valid
в форме, чтобы убедиться, что в одном из полей есть данные, прежде чем делать что-то вроде super.is_valid()
(в противном случае возвращается true, поэтому я не выдаю ошибку для пустого form), а также функцию pre-save
в форме, которая принимает объекты user
и client
и помещает их в поля и проверяет наличие номера телефона перед сохранением.
- Перезаписать
is_valid()
, чтобы пустые значения могли пройти через
- Создайте
pre-save()
для загрузки в User
и Client
в модель и отмените, если можете, если нет значения для number
ЭТО СУМАСШЕДШЕЕ !!!
Единственное, о чем я могу думать, это сделать phone_type
и number
в ClientPhone
модели blank=True, null=True
, чтобы у меня могли быть дополнительные поля телефона
ЭТО БЕЗУМНО КАК ХОРОШО !!!
Почему я должен нарушать целостность моей модели, чтобы иметь поле опции в одной из моих форм ???
EDIT:
view.py оказался чище, когда я сделал следующее для файла forms.py:
class ClientDetailsForm(ModelForm):
class Meta:
model = ClientDetails
exclude = ('client', 'created', 'created_by')
def CustomSave(self,c,u):
t = self.save(commit=False)
t.client = c
t.created_by = u
t.first_name = self.cleaned_data['first_name'].capitalize()
t.middle_name = self.cleaned_data['first_name'].capitalize()
t.last_name = self.cleaned_data['first_name'].capitalize()
t.save()
class ClientAddressForm(ModelForm):
class Meta:
model = ClientAddress
exclude = ('client', 'created', 'created_by')
def CustomSave(self,c,u):
t = self.save(commit=False)
t.client = c
t.created_by = u
t.address_1 = self.cleaned_data['address_1'].capitalize()
t.address_2 = self.cleaned_data['address_2'].capitalize()
t.address_3 = self.cleaned_data['address_3'].capitalize()
t.address_4 = self.cleaned_data['address_4'].capitalize()
t.post_code = self.cleaned_data['post_code'].upper()
t.save()
class ClientPhoneForm(ModelForm):
number = UKPhoneNumberField()
class Meta:
model = ClientPhone
exclude = ('client', 'created', 'created_by')
def CustomSave(self,c,u):
t = self.save(commit=False)
t.client = c
t.created_by = u
t.save()
class ClientOtherPhoneForm(ModelForm):
number = UKPhoneNumberField(required=False)
class Meta:
model = ClientPhone
exclude = ('client', 'created', 'created_by')
def CustomSave(self,c,u):
t = self.save(commit=False)
t.client = c
t.created_by = u
t.save()