Django表单验证基于字段是否有值

发布于 2024-10-12 16:57:37 字数 4564 浏览 8 评论 0原文

  1. 当我提交一个选择了 phone_type 的空表单(对于 formHomePhone)时,表单返回其自身,而没有在 phone_type 中选择的值规定此字段是必需的

  2. 正如您从视图中看到的那样,表单中的第一个电话号码是必需的,但其他电话号码不是。我只想在存在价值的情况下处理它们。尽管当我在空表单上单击“提交”时,附加电话号码字段会从 UKPhoneNumberField > 中抛出错误。 电话号码必须包含区号。如何仅在相关字段中有号码时进行验证?

我有一个像这样的 view.py 文件

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))

,一个像这样的 forms.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')

和一个像这样的 models.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)

顺便说一句(我知道我的 new_client_view 函数不是很干。任何建议都是非常感谢)

  1. When I submit an empty form with a phone_type selected (for formHomePhone) the form returns its self without a value selected in phone_type stipulating This field is required

  2. As you can see from the view The first phone number in the form is required but the other phone numbers are not. I only want to process them if there is a value present. Though when I click submit on an empty form the additional phone number fields throw up an error from the UKPhoneNumberField > Phone number must include an area code. How can I only validate when there is a number in the respected field?

I have a view.py file like this

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))

a forms.py like this:

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')

and a models.py like this:

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)

BTW(my new_client_view function is not very DRY I know. Any recommendations would be gratefully received)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静若繁花 2024-10-19 16:57:37

如果要在 ModelForm 字段为空时停止对其进行验证,请在模型定义中设置 Blank=True、null=True。

如果您不想更改模型,可以覆盖 ModelForm 中的 required attr(见下文),但请记住,您的 form.save() 方法可能会尝试保留 null数据库期望非空值的值。

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

If you want to stop ModelForm fields being validated when they're empty, set blank=True, null=True in the model definition.

If you don't want to change the model, you can override the required attr in the ModelForm (see below), but bear in mind then that your form.save() method may try to leave null values where the DB expects non-nulls.

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

UPDATE
Here's a totally different approach, given that the OP's comments seem to imply that validation between forms may be what he's after:

If you want one of your current forms to behave a certain way based on what's in another form, you're talking cross-form validation, which isn't possible as the cleaning methods of forms are not easily aware of any other forms being handled by that view.

Instead, I'd recommend making a new forms.Form class that has all the fields of the models you want to deal with, but which is not a ModelForm. You can then add a save() (or process() or whatever) method to that Form that will do the fandango you currently have in your view. That may make your code slightly neater, too.

You'll need to pass in the request.user into the form as an argument (a kwarg is easier to get right) so that you can set the appropriate user on the models you're saving.

But of course, let's not forget about the validation, which I recommend you do in the main clean() method of that form, which will have access to all the fields you need to juggle.

So, as some quick untested code:

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
臻嫒无言 2024-10-19 16:57:37

我找到了一个类似这样的答案(是的,我知道这很愚蠢!)

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,这样我就不会为空表单引发错误)以及表单上的 presave 函数,该函数采用userclient 对象,并将它们放入字段中,并在保存之前检查是否有电话号码。

  1. 覆盖 is_valid() 以确保空白值可以通过
  2. Create pre-save() 加载到 UserClient 进入模型,如果可以的话,如果 number 没有值 就中止

这太疯狂了!!!

我唯一能想到的就是制作 ClientPhone 模型中的phone_typenumber blank=True, null=True 以便我可以拥有可选的电话字段

这也太疯狂了!!!

为什么我必须破坏模型的完整性才能在我的表单之一中拥有一个选项字段???

编辑:

当我对 forms.py 文件执行以下操作时,view.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()

I found an answer that goes something like this (yes I know it's stupid!)

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))

I think I need to overwrite the is_valid function on the form to make sure there is data in one of the fields before doing something like super.is_valid() (else returning true so I don't raise an error for an empty form) and also a pre-save function on the form that takes the user and client objects and puts them into the fields and checks there is a phone number before saving.

  1. Overwrite is_valid() to make sure blank values can get through
  2. Create pre-save() to load in User and Client into the model and abort if you can if there is no value for number

THIS IS CRAZY!!!

The only other thing I can think of is making phone_type and number in the ClientPhone model blank=True, null=True so that I can have optional phone fields

THATS CRAZY AS WELL!!!

Why should I have to break the integrity of my model just to have an option field in one of my forms???

EDIT:

view.py turned out cleaner when I did the following to the forms.py file:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文