mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-09 01:49:35 -06:00
20645 CSVChoiceField use default if blank
This commit is contained in:
parent
0b61d69e05
commit
90712fa865
@ -18,6 +18,20 @@ __all__ = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CSVSelectWidget(forms.Select):
|
||||||
|
"""
|
||||||
|
Custom Select widget for CSV imports that treats blank values as omitted.
|
||||||
|
This allows model defaults to be applied when a CSV field is present but empty.
|
||||||
|
"""
|
||||||
|
def value_omitted_from_data(self, data, files, name):
|
||||||
|
# Check if value is omitted using parent behavior
|
||||||
|
if super().value_omitted_from_data(data, files, name):
|
||||||
|
return True
|
||||||
|
# Treat blank/empty strings as omitted to allow model defaults
|
||||||
|
value = data.get(name)
|
||||||
|
return value == '' or value is None
|
||||||
|
|
||||||
|
|
||||||
class CSVChoicesMixin:
|
class CSVChoicesMixin:
|
||||||
STATIC_CHOICES = True
|
STATIC_CHOICES = True
|
||||||
|
|
||||||
@ -29,8 +43,9 @@ class CSVChoicesMixin:
|
|||||||
class CSVChoiceField(CSVChoicesMixin, forms.ChoiceField):
|
class CSVChoiceField(CSVChoicesMixin, forms.ChoiceField):
|
||||||
"""
|
"""
|
||||||
A CSV field which accepts a single selection value.
|
A CSV field which accepts a single selection value.
|
||||||
|
Treats blank CSV values as omitted to allow model defaults.
|
||||||
"""
|
"""
|
||||||
pass
|
widget = CSVSelectWidget
|
||||||
|
|
||||||
|
|
||||||
class CSVMultipleChoiceField(CSVChoicesMixin, forms.MultipleChoiceField):
|
class CSVMultipleChoiceField(CSVChoicesMixin, forms.MultipleChoiceField):
|
||||||
@ -46,7 +61,12 @@ class CSVMultipleChoiceField(CSVChoicesMixin, forms.MultipleChoiceField):
|
|||||||
|
|
||||||
|
|
||||||
class CSVTypedChoiceField(forms.TypedChoiceField):
|
class CSVTypedChoiceField(forms.TypedChoiceField):
|
||||||
|
"""
|
||||||
|
A CSV field for typed choice values.
|
||||||
|
Treats blank CSV values as omitted to allow model defaults.
|
||||||
|
"""
|
||||||
STATIC_CHOICES = True
|
STATIC_CHOICES = True
|
||||||
|
widget = CSVSelectWidget
|
||||||
|
|
||||||
|
|
||||||
class CSVModelChoiceField(forms.ModelChoiceField):
|
class CSVModelChoiceField(forms.ModelChoiceField):
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from django.test import TestCase
|
|||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
from netbox.choices import ImportFormatChoices
|
from netbox.choices import ImportFormatChoices
|
||||||
from utilities.forms.bulk_import import BulkImportForm
|
from utilities.forms.bulk_import import BulkImportForm
|
||||||
|
from utilities.forms.fields.csv import CSVSelectWidget
|
||||||
from utilities.forms.forms import BulkRenameForm
|
from utilities.forms.forms import BulkRenameForm
|
||||||
from utilities.forms.utils import get_field_value, expand_alphanumeric_pattern, expand_ipaddress_pattern
|
from utilities.forms.utils import get_field_value, expand_alphanumeric_pattern, expand_ipaddress_pattern
|
||||||
|
|
||||||
@ -448,3 +449,35 @@ class GetFieldValueTest(TestCase):
|
|||||||
get_field_value(form, 'site'),
|
get_field_value(form, 'site'),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CSVSelectWidgetTest(TestCase):
|
||||||
|
"""
|
||||||
|
Validate that CSVSelectWidget treats blank values as omitted.
|
||||||
|
This allows model defaults to be applied when CSV fields are present but empty.
|
||||||
|
Related to issue #20645.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_blank_value_treated_as_omitted(self):
|
||||||
|
"""Test that blank string values are treated as omitted"""
|
||||||
|
widget = CSVSelectWidget()
|
||||||
|
data = {'test_field': ''}
|
||||||
|
self.assertTrue(widget.value_omitted_from_data(data, {}, 'test_field'))
|
||||||
|
|
||||||
|
def test_none_value_treated_as_omitted(self):
|
||||||
|
"""Test that None values are treated as omitted"""
|
||||||
|
widget = CSVSelectWidget()
|
||||||
|
data = {'test_field': None}
|
||||||
|
self.assertTrue(widget.value_omitted_from_data(data, {}, 'test_field'))
|
||||||
|
|
||||||
|
def test_missing_field_treated_as_omitted(self):
|
||||||
|
"""Test that missing fields are treated as omitted"""
|
||||||
|
widget = CSVSelectWidget()
|
||||||
|
data = {}
|
||||||
|
self.assertTrue(widget.value_omitted_from_data(data, {}, 'test_field'))
|
||||||
|
|
||||||
|
def test_valid_value_not_omitted(self):
|
||||||
|
"""Test that valid values are not treated as omitted"""
|
||||||
|
widget = CSVSelectWidget()
|
||||||
|
data = {'test_field': 'valid_value'}
|
||||||
|
self.assertFalse(widget.value_omitted_from_data(data, {}, 'test_field'))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user