当我提交一个选中了phone_type
的空表单(对于formHomePhone
)时,表单会返回自己,而不会在phone_type
中选择This field is required
UKPhoneNumberField
< / p>
从视图中可以看出表格中的第一个电话号码是必需的,但其他电话号码不是。如果存在值,我只想处理它们。虽然当我在空表单上点击提交时,其他电话号码字段会从Phone number must include an area code.
&gt;中引发错误。 def new_client_view(request):
if request.method == 'POST':
formDetails = ClientDetailsForm(request.POST)
formAddress = ClientAddressForm(request.POST)
formHomePhone = ClientPhoneForm(request.POST)
formWorkPhone = ClientOtherPhoneForm(request.POST)
formMobilePhone = ClientOtherPhoneForm(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']:
fpw = formWorkPhone.save(commit=False)
fpw.client = c.id
fpw.created_by = request.user
if fpw.is_valid():
fpw.save()
if 'p3-number' in request.POST and request.POST['p3-number']:
fpm = formMobilePhone.save(commit=False)
fpm.client = c
fpm.created_by = request.user
if fpm.is_valid():
fpm.save()
return render_to_response('client/client.html', context_instance=RequestContext(request))
else:
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))
如何才能在尊重字段中存在数字时进行验证?
我有一个像这样的view.py文件
class ClientDetailsForm(ModelForm):
class Meta:
model = ClientDetails
exclude = ('client', 'created', 'created_by')
class ClientAddressForm(ModelForm):
class Meta:
model = ClientAddress
exclude = ('client', 'created', 'created_by')
class ClientPhoneForm(ModelForm):
number = UKPhoneNumberField()
class Meta:
model = ClientPhone
exclude = ('client', 'created', 'created_by')
class ClientOtherPhoneForm(ModelForm):
number = UKPhoneNumberField(required=False)
class Meta:
model = ClientPhone
exclude = ('client', 'created', 'created_by')
像这样的forms.py:
MARITAL_STATUS_CHOICES = (
...
)
NAME_TITLE_CHOICES = (
...
)
PHONE_CHOICES = (
('home', 'Home'),
('home2', 'Home 2'),
('mobi', 'Mobile'),
('mobi2', 'Mobile 2'),
('work', 'Work'),
('work2', 'Work 2'),
)
class Client(models.Model):
closed = models.DateTimeField(blank=True, null=True)
closed_by = models.ForeignKey(User, blank=True, null=True)
comment = models.TextField(blank=True, null=True)
def __unicode__(self):
return u'%s' % (self.id)
class ClientDetails(models.Model):
...
class ClientAddress(models.Model):
...
class ClientPhone(models.Model):
client = models.ForeignKey(Client, null=True)
created = models.DateTimeField(default=datetime.now)
created_by = models.ForeignKey(User, blank=True, null=True)
phone_type = models.CharField(max_length=5, choices=PHONE_CHOICES)
number = models.CharField(max_length=24)
和models.py这样:
new_client_view
BTW(我的{{1}}功能不是很干我知道。会很感激地收到任何建议。
答案 0 :(得分:8)
如果要在ModelForm字段为空时停止验证,请在模型定义中设置blank = True,null = True。
如果您不想更改模型,可以覆盖ModelForm中的required
attr(参见下文),但请记住,form.save()方法可能会尝试保留null DB期望非空值的值。
class FooForm(forms.ModelForm):
class Meta:
#exclude etc as you wish
def __init__(self, *args, **kwargs):
#init the form as usual
super(FooForm, self).__init__(*args, **kwargs)
#then change the required status on the fields:
self.fields['baz'].required = False
<强>更新强> 这是一个完全不同的方法,因为OP的评论似乎意味着形式之间的验证可能是他所追求的:
如果您希望当前某个表单基于另一种形式的某种方式表现出来,那么您就是在谈论跨表单验证,这是不可能的,因为表单的清理方法不容易识别任何其他表单表格由该视图处理。
相反,我建议创建一个新的forms.Form类,它包含您要处理的模型的所有字段,但不是ModelForm。然后,您可以向该表单添加save()
(或process()
或其他)方法,这些方法将执行您在视图中当前拥有的fandango。这可能会使你的代码稍微整洁。
您需要将request.user作为参数传递给表单(kwarg更容易正确),以便您可以在要保存的模型上设置适当的用户。
但是,当然,我们不要忘记验证,我建议您在该表单的主要clean()方法中进行验证,该方法可以访问您需要处理的所有字段。
所以,作为一些快速未经测试的代码:
from django import forms
from django.forms.util import ErrorList
class ClientForm(forms.Form):
## define your fields here ##
home_phone = forms.CharField(required=False)
# etc etc
def __init__(self, *args, **kwargs):
"""
NB: in the view you'll need to call the form's constructor with
keyword arguments for client (the client whose details are being
edited) and user (ie: request.user)
"""
#before the form is initialised, grab the two extra objects we'll
#need in save()
self.client = kwargs.pop('client')
#NB:this will explode if there is no client kwarg present
self.user = kwargs.pop('user') #ditto, for a 'user' argument
#now carry on with the standard form initialisation
super(ClientForm, self).__init__(*args, **kwargs)
def clean(self):
#probe your cleaned data here and enforce any cross-field dependencies you wish
if self.cleaned_data.get('foo') and not self.cleaned_data.get('bar'):
self._errors['foo'] = ErrorList(["A Foo should only be present if there\'s not a Bar"])
# NB: only override a value in an _errors dict if you're sure there is
# nothing in there already (ie: the foo field has been cleaned and is
# present in cleaned_data)
# Otherwise, you should append() a string to the ErrorList in question
return self.cleaned_data
def save(self):
#what you have in the view is doing a lot of the legwork, so extend that
#code here to get or create the relevant ClientHomePhone etc models
#based on lookups related to self.client, which we set in __init__() above
#also, remember you'll have access to self.user which is the user who is
#creating/editing so you can set this for created_by
return self.client # or some other relevant entity, if you wish
答案 1 :(得分:0)
我找到了类似这样的答案(是的,我知道这很愚蠢!)
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,所以我不会提高表单上的pre-save
函数,表单上有一个user
函数,它将client
和is_valid()
个对象放入字段,并在保存前检查是否有电话号码。< / p>
pre-save()
以确保空白值可以通过User
以将Client
和number
加载到模型中,如果phone_type
这太疯狂了!!!
我唯一能想到的是在number
模型ClientPhone
中设置blank=True, null=True
和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()
,以便我可以选择手机字段
那太疯狂了!!!
为什么我必须打破模型的完整性只是为了在我的一个表单中有一个选项字段???
view.py变得更干净了:
{{1}}