diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index 421c3d824..ac9b0ea9a 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -1,5 +1,6 @@ from django import forms from django.contrib.contenttypes.models import ContentType +from django.core.validators import EMPTY_VALUES from django.utils.translation import gettext_lazy as _ from timezone_field import TimeZoneFormField @@ -498,7 +499,8 @@ class ModuleTypeForm(NetBoxModelForm): if self.cleaned_data.get('profile'): self.instance.attribute_data = { name[5:]: self.cleaned_data[name] # Remove the attr_ prefix - for name in self.attr_fields if self.cleaned_data[name] is not None + for name in self.attr_fields + if self.cleaned_data.get(name) not in EMPTY_VALUES } return super()._post_clean() diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index 1fc228abe..94fb37987 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -361,7 +361,7 @@ class AttributeFiltersMixin: if data is not None: for key, value in data.items(): if key.startswith(self.attribute_filter_prefix): - # Attempt to case the value to a native JSON type + # Attempt to cast the value to a native JSON type try: value = json.loads(value) except (ValueError, json.JSONDecodeError): diff --git a/netbox/utilities/jsonschema.py b/netbox/utilities/jsonschema.py index 5f2887eb8..b5a4ada04 100644 --- a/netbox/utilities/jsonschema.py +++ b/netbox/utilities/jsonschema.py @@ -87,10 +87,13 @@ class JSONSchemaProperty: # Choices if self.enum: - field_kwargs['choices'] = [(v, v) for v in self.enum] + choices = [(v, v) for v in self.enum] + if not required: + choices = [(None, ''), *choices] + field_kwargs['choices'] = choices # String validation - elif self.type == PropertyTypeEnum.STRING: + if self.type == PropertyTypeEnum.STRING.value: if self.minLength is not None: field_kwargs['min_length'] = self.minLength if self.maxLength is not None: @@ -101,16 +104,16 @@ class JSONSchemaProperty: ] # Integer/number validation - elif self.type in (PropertyTypeEnum.INTEGER, PropertyTypeEnum.NUMBER): + elif self.type in (PropertyTypeEnum.INTEGER.value, PropertyTypeEnum.NUMBER.value): + field_kwargs['widget'] = forms.NumberInput(attrs={'step': 'any'}) if self.minimum: field_kwargs['min_value'] = self.minimum if self.maximum: - field_kwargs['min_value'] = self.maximum + field_kwargs['max_value'] = self.maximum if self.multipleOf: field_kwargs['validators'] = [ MultipleOfValidator(multiple=self.multipleOf) ] - return self.field_class(**field_kwargs) @property