I'm trying to set a simple form, for user to input IP subnet into my django app. I want to validate that IP + Mask is a subnet address. I'm using CreateView with IpRangeForm. However, I've noticed a problem, that when I override ModelForm clean method, my model validation doesn't work.


class IpSubnet(models.Model):
    ip = models.GenericIPAddressField(verbose_name="IP", protocol='IPv4')    
    mask = models.IntegerField(verbose_name="Mask", default=24, validators=[MaxValueValidator(32), MinValueValidator(0)]))


class IpSubnetCreateView(SuccessMessageMixin, CreateView):
    form_class = IpSubnetForm 
    model = IpSubnet   
    success_url = '/front/'
    success_message = "%(ip)s/%(mask)s added"


class IpSubnetForm(forms.ModelForm):
    class Meta:
        model= IpSubnet
        fields = ( 'ip','mask')

    def clean(self):
        cleaned_data = super(IpSubnetForm, self).clean()
        ip = cleaned_data.get('ip')
        mask = cleaned_data.get('mask')

        subnet = ipcalc.Network(ip + "/" + str(mask))
        if ip != subnet.network():
            raise ValidationError(
                _('%(ip)s/%(mask)s is not a network address (network address: %(network)s/%(mask)s)'),
                params={'ip':str(ip), 'mask' : str(mask), 'network':str(subnet.network())},
        return cleaned_data

If I delete my clean method, model validation works fine. With my clean method, only the subnet validation works, so user can input i.e. chars into IP field. I don't see any difference if I add or delete call to parent:

super(IpSubnetForm, self).clean()

Therefore it looks like in my case I should use some other way?

How can I fix it, what mistake am I making?

1 Answers

Pumar On Best Solutions

So after more investigetion into how validation in django works, and thanks to this answer, this is the solution:

def clean(self):      
    cleaned_data = super(IpRangeForm, self).clean()

    if any(self.errors):
        return self.errors

The problem was that validation did run, but it didn't stop from running the cleanning method. Therefore it raises an exception, about me trying to work with NoneType.