1👍
When you’re doing validators=[validate_dmvpn_ip('','172.16.100.')]
, you end up with the return value of calling the validation function as the validator (which is validators=[None]
because you’re not returning anything). It looks like you’re trying to create a customizable validation function. For that you’ll need to write a function that returns a another:
def validate_dmvpn_ip(subnet):
from django.core.exceptions import ValidationError
def validator(value):
if subnet not in value or value != '0.0.0.0':
raise ValidationError('Invalid IP address, please check corrent octects have been assigned')
return validator
And you use it like so:
# outside model:
main_validator = validate_dmvpn_ip('172.16.100.')
main_validator.__name__ = 'main_validator'
main_validator.__module__ = 'path.to.this.module'
# inside model
dmvpn_dsl = models.GenericIPAddressField(protocol='IPv4', verbose_name="DMVPN DSL IP", \
validators=[main_validator], blank=True, null=True)
The outer function returns another function that takes a value to validate, but still has access to the subnet to validate against.
Notice how I’m signing the validator to another variable and assigning the __name__
and __module__
attributes. While this is normally not needed, django needs to be able to refer to the validator directly for migration purposes, and a returned function is not assigned anywhere. Of course if you only have one such validator, you can hardcode the subnet and avoid this mess:
def validate_dmvpn_ip(value):
subnet = '172.16.100.'
from django.core.exceptions import ValidationError
if subnet not in value or value != '0.0.0.0':
raise ValidationError('Invalid IP address, please check corrent octects have been assigned')
and
dmvpn_dsl = models.GenericIPAddressField(protocol='IPv4', verbose_name="DMVPN DSL IP", \
validators=[validate_dmvpn_ip], blank=True, null=True)
To learn more about nested functions (closures), take a look at decorators in python which are basically this + special @
syntax.