Royal
Royal

Reputation: 752

validate text field and number

forms.py

class PhoneinfoForm(forms.ModelForm):

    pname = forms.CharField(required=True)
    pnumber = forms.IntegerField(required=True)
    gname = forms.CharField(required=False)
    gnumber = forms.IntegerField(required=False)
    class Meta:
        model = Phone_info
        fields = ['pname','pnumber','gname','gnumber']

    def clean(self):
        cleaned_data = self.cleaned_data
        pname = cleaned_data.get("pname")
        pnumber = cleaned_data.get("pnumber")
        gname = cleaned_data.get("gname")
        gnumber = cleaned_data.get("gnumber")

        if 'pname' and 'pnumber' not in cleaned_data: 
            raise forms.ValidationError
        if 'gname' and 'gnumber' not in cleaned_data: 
            raise forms.ValidationError

        return cleaned_data

I am trying to validate name and number. In my case, pname and pnumber are one set and mandatory field, that i achieved my giving required=True.

2nd thing is gname and gnumber are not mandatory, but if gnumber is entered then it is taking blank to gname (if nothing enteredin gname it is accepting) that should not happen. If number is entered it should not accept without name or vice versa.

My code is not working for 2nd choice, how to validate this.

Thanks

Upvotes: 1

Views: 1077

Answers (1)

stalk
stalk

Reputation: 12054

There are several bad things in your code:

1) When using forms.ModelForm it is not needed to declare fields in a form, if corresponding model fields have same constraints. From question example, if in model Phone_info corresponding fields have same blank attributes as form's required, it is not needed to declare fields again in a modelform.

2) As pname and pnumber are required, you don't need to check manually that they are filled. It is already done by ModelForm. So this is odd and must be removed:

if 'pname' and 'pnumber' not in cleaned_data: 
    raise forms.ValidationError

3) This line will not do what expected:

if 'gname' and 'gnumber' not in cleaned_data

It will first check condition 'gnumber' not in cleaned_data. The result will be the boolean (True/False). And then condition if 'gname' and False/True will be applied.

What you want is:

gname = self.cleaned_data.get("gname", None)
gnumber = self.cleaned_data.get("gnumber", None)
if gname and gnumber is None:
    raise forms.ValidationError("gnumber must be filled")
if gnumber is not None and not gname:
    raise forms.ValidationError("gname must be filled")

4) As you've mentiond in p.3, forms.ValidationError must be initialized when raised:

raise forms.ValidationError("Error message")

So result code:

class PhoneinfoForm(forms.ModelForm):

    # delete these fields, if they are the same, as in Phone_info
    pname = forms.CharField(required=True)
    pnumber = forms.IntegerField(required=True)
    gname = forms.CharField(required=False)
    gnumber = forms.IntegerField(required=False)

    class Meta:
        model = Phone_info
        fields = ['pname', 'pnumber', 'gname', 'gnumber']

    def clean(self):
        gname = self.cleaned_data.get("gname", None)
        gnumber = self.cleaned_data.get("gnumber", None)
        if gname and gnumber is None:
            raise forms.ValidationError("gnumber must be filled")
        if gnumber is not None and not gname:
            raise forms.ValidationError("gname must be filled")

        return self.cleaned_data

Upvotes: 1

Related Questions