Sorry, I’m new to Django and this forum, I’ll keep in mind.
This is an abstract, clean is not overridden:
class BaseModel(models.Model):
description = models.CharField(
max_length=100,
blank=True
)
login = models.CharField(
help_text='Subscriber\'s login. If not specified, the IP address or prefix value is used by default',
max_length=100,
blank=True
)
is_multi_ip_login = models.BooleanField(
help_text='If checked login is considered to be common for multiple IP addresses and/or prefixes',
verbose_name='Login multiple',
default=True
)
policing_profile = models.ForeignKey(
PolicingProfile,
verbose_name='Policing profile',
on_delete=models.PROTECT,
blank=True,
null=True
)
service_profiles = models.ManyToManyField(
ServiceProfile,
verbose_name='Service profiles',
blank=True
)
session_timeout = models.PositiveIntegerField(
help_text='Reauthentication period in seconds',
default=300
)
session_status = models.CharField(
verbose_name='Session status',
choices=AccessStatusChoices,
default=AccessStatusChoices.ACCEPT
)
created = models.DateTimeField(
auto_now_add=True
)
last_updated = models.DateTimeField(
auto_now=True
)
comments = models.TextField(
blank=True
)
class Meta:
abstract = True
The form:
class PrefixForm(ModelForm):
service_profiles = ModelMultipleChoiceField(
queryset=ServiceProfile.objects.all(),
widget=SelectMultiple(attrs={
'class': 'form-select tom-select hidden-on-load',
'multiple': 'multiple',
'style': 'display: none;',
'data-ts-placeholder': ''
}),
required=False
)
class Meta:
model = Prefix
fields = ['prefix', 'description', 'login', 'is_multi_ip_login', 'policing_profile',
'service_profiles', 'session_timeout', 'session_status', 'comments']
widgets = {
'prefix': TextInput(attrs={'class': 'form-control'}),
'description': TextInput(attrs={'class': 'form-control'}),
'login': TextInput(attrs={'class': 'form-control'}),
'is_multi_ip_login': CheckboxInput(attrs={'class': 'form-check-input'}),
'policing_profile': Select(attrs={'class': 'form-select'}),
'session_timeout': NumberInput(attrs={'class': 'form-control'}),
'session_status': Select(attrs={'class': 'form-control'}),
'comments': Textarea(attrs={'class': 'form-control'}),
}
The view:
class PrefixCreateView(CreateView):
model = Prefix
template_name = 'ipam/prefix_add.html'
form_class = PrefixForm
success_url = reverse_lazy('ipam:prefix_list')
def form_valid(self, form):
messages.success(self.request, 'Prefix created successfully.')
return super().form_valid(form)
For example, if I’ll try to enter the invalid prefix 10.0.0.0/244 (there is an extra digit in the prefix length), the traceback will be:
ERROR 2025-11-21 10:45:21,179 log Internal Server Error: /ipam/prefixes/add/
Traceback (most recent call last):
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\strategy\ipv4.py”, line 128, in str_to_int
packed = _inet_pton(AF_INET, addr)
^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\fbsocket.py”, line 147, in inet_pton
return _inet_pton_af_inet(ip_string)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\fbsocket.py”, line 135, in _inet_pton_af_inet
raise invalid_addr
OSError: illegal IP address string ‘1’
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init_.py”, line 346, in init
self._value = self._module.str_to_int(addr, flags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\strategy\ipv4.py”, line 132, in str_to_int
raise error
netaddr.core.AddrFormatError: ‘1’ is not a valid IPv4 address string!
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init_.py”, line 1034, in init
value, prefixlen = parse_ip_network(
^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init_.py”, line 902, in parse_ip_network
ip = IPAddress(val1, module.version, flags=INET_PTON)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init_.py”, line 348, in init
raise AddrFormatError(
netaddr.core.AddrFormatError: base address ‘1’ is not IPv4
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\core\handlers\exception.py”, line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\core\handlers\base.py”, line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\views\generic\base.py”, line 105, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\views\generic\base.py”, line 144, in dispatch
return handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\views\generic\edit.py”, line 182, in post
return super().post(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\views\generic\edit.py”, line 150, in post
if form.is_valid():
^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\forms\forms.py”, line 206, in is_valid
return self.is_bound and not self.errors
^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\forms\forms.py”, line 201, in errors
self.full_clean()
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\forms\forms.py”, line 339, in full_clean
self.post_clean()
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\forms\models.py”, line 498, in post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\django\db\models\base.py”, line 1654, in full_clean
self.clean()
File “C:\Users\Astiks\PycharmProjects\skat\ipam\models.py”, line 109, in clean
overlapping_prefixes = self.get_overlapping_prefixes()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat\ipam\models.py”, line 115, in get_overlapping_prefixes
overlapping_prefix_pks = [prefix.pk for prefix in other_prefixes if IPSet(prefix.prefix) & IPSet(self.prefix)]
^^^^^^^^^^^^^^^^^^
File “C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip\sets.py”, line 117, in init
for cidr in cidr_merge(mergeable):
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init.py", line 1675, in cidr_merge
net = IPNetwork(ip)
^^^^^^^^^^^^^
File "C:\Users\Astiks\PycharmProjects\skat.venv\Lib\site-packages\netaddr\ip_init.py", line 1045, in init
raise AddrFormatError(‘invalid IPNetwork %s’ % (addr,))
netaddr.core.AddrFormatError: invalid IPNetwork 1
ERROR 2025-11-21 10:45:21,374 basehttp “POST /ipam/prefixes/add/ HTTP/1.1” 500 177508
In this case, I expect that an AddrFormatError exception would be raised in IPNetworkField’s to_python and the validation process would fail, but this is not the case.
I added some logging to the clean methods:
log = logging.getLogger(__name__)
class IPNetworkField(CharField):
default_validators = [prefix_validator]
def from_db_value(self, value, expression, connection):
return self.to_python(value)
def get_internal_type(self):
return 'CharField'
def to_python(self, value):
if not value:
return value
try:
return IPNetwork(value)
except AddrFormatError:
log.error(f'Invalid IP address {value}')
raise ValidationError(f'to_python: Invalid IP Network format: {value}')
except (TypeError, ValueError) as e:
raise ValidationError(e)
def get_prep_value(self, value):
if not value:
return None
if isinstance(value, list):
return [str(self.to_python(v)) for v in value]
return str(self.to_python(value))
def clean(self, value, model_instance):
log.info(f'Input: {value}')
log.info(f'Execute to_python() method')
value = self.to_python(value)
log.info(f'Execute validate() method')
self.validate(value, model_instance)
self.run_validators(value)
return value
def validate(self, value, model_instance):
log.info('Validate...')
super().validate(value, model_instance)
def run_validators(self, value):
log.info('Run validators...')
super().run_validators(value)
Then if I try to enter invalid prefix, this log is displayed in the console:
INFO 2025-11-21 11:43:00,437 fields Input: 10.0.0.0/244
INFO 2025-11-21 11:43:00,438 fields Execute to_python() method
ERROR 2025-11-21 11:43:00,438 fields to_python: Invalid IP address 10.0.0.0/244
ERROR 2025-11-21 11:43:00,583 log Internal Server Error: /ipam/prefixes/add/
Traceback (most recent call last):
... the same traceback ...
I’m confused, clean in IPNetworkField fails, why is Django trying to clean model anyway?