diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 2c6b6cb65..751b2ddb0 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -94,7 +94,7 @@ class CustomFieldModelCSVForm(CustomFieldModelForm): # Append form fields for cf in CustomField.objects.filter(obj_type=self.obj_type): field_name = 'cf_{}'.format(cf.name) - self.fields[field_name] = cf.to_form_field() + self.fields[field_name] = cf.to_form_field(for_csv_import=True) # Annotate the field in the list of CustomField form fields self.custom_fields.append(field_name) diff --git a/netbox/extras/models.py b/netbox/extras/models.py index db42fc845..70f7661c8 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -15,7 +15,7 @@ from django.utils.text import slugify from taggit.models import TagBase, GenericTaggedItemBase from utilities.fields import ColorField -from utilities.forms import DatePicker, LaxURLField, StaticSelect2, add_blank_choice +from utilities.forms import CSVChoiceField, DatePicker, LaxURLField, StaticSelect2, add_blank_choice from utilities.utils import deepmerge, render_jinja2 from .choices import * from .constants import * @@ -282,12 +282,13 @@ class CustomField(models.Model): return self.choices.get(pk=int(serialized_value)) return serialized_value - def to_form_field(self, set_initial=True, enforce_required=True): + def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import=False): """ Return a form field suitable for setting a CustomField's value for an object. set_initial: Set initial date for the field. This should be False when generating a field for bulk editing. enforce_required: Honor the value of CustomField.required. Set to False for filtering/bulk editing. + for_csv_import: Return a form field suitable for bulk import of objects in CSV format. """ initial = self.default if set_initial else None required = self.required if enforce_required else False @@ -320,17 +321,19 @@ class CustomField(models.Model): # Select elif self.type == CustomFieldTypeChoices.TYPE_SELECT: choices = [(cfc.pk, cfc.value) for cfc in self.choices.all()] - # TODO: Accommodate bulk edit/filtering - # if not self.required or bulk_edit or filterable_only: + if not required: choices = add_blank_choice(choices) + # Set the initial value to the PK of the default choice, if any if set_initial: default_choice = self.choices.filter(value=self.default).first() if default_choice: initial = default_choice.pk - field = forms.TypedChoiceField( - choices=choices, coerce=int, required=required, initial=initial, widget=StaticSelect2() + + field_class = CSVChoiceField if for_csv_import else forms.ChoiceField + field = field_class( + choices=choices, required=required, initial=initial, widget=StaticSelect2() ) # URL diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index c175df3cd..a14ec9305 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -442,20 +442,6 @@ class CSVChoiceField(forms.ChoiceField): return self.choice_values[value] -class CSVCustomFieldChoiceField(forms.TypedChoiceField): - """ - Invert the choice tuples: CSV import takes the human-friendly label as input rather than the database value - """ - def __init__(self, *args, **kwargs): - - if 'choices' in kwargs: - kwargs['choices'] = { - label: value for value, label in kwargs['choices'] - } - - super().__init__(*args, **kwargs) - - class ExpandableNameField(forms.CharField): """ A field which allows for numeric range expansion