From d8da99f2258b1a3d662b1f26d515d0cf869c1245 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 27 Jul 2023 09:28:31 -0400 Subject: [PATCH] Misc cleanup --- docs/models/extras/customfieldchoiceset.md | 7 +++++-- netbox/extras/api/views.py | 9 +++------ netbox/extras/choices.py | 6 +++--- netbox/extras/forms/bulk_import.py | 2 +- netbox/extras/forms/model_forms.py | 1 - netbox/extras/models/customfields.py | 6 +++--- netbox/extras/tables/tables.py | 8 +++----- netbox/netbox/tables/columns.py | 4 ++-- netbox/utilities/forms/widgets/misc.py | 11 +++++++++++ 9 files changed, 31 insertions(+), 23 deletions(-) diff --git a/docs/models/extras/customfieldchoiceset.md b/docs/models/extras/customfieldchoiceset.md index c87c70cee..4f4e134ec 100644 --- a/docs/models/extras/customfieldchoiceset.md +++ b/docs/models/extras/customfieldchoiceset.md @@ -1,6 +1,8 @@ # Custom Field Choice Sets -Single- and multi-selection [custom fields documentation](../../customization/custom-fields.md) must define a set of valid choices from which the user may choose when defining the field value. These choices are defined as sets that may be reused among multiple custom fields. +Single- and multi-selection [custom fields](../../customization/custom-fields.md) must define a set of valid choices from which the user may choose when defining the field value. These choices are defined as sets that may be reused among multiple custom fields. + +A choice set must define a base choice set and/or a set of arbitrary extra choices. ## Fields @@ -12,12 +14,13 @@ The human-friendly name of the choice set. The set of pre-defined choices to include. Available sets are listed below. This is an optional setting. +* IATA airport codes * ISO 3166 - Two-letter country codes * UN/LOCODE - Five-character location identifiers ### Extra Choices -A list of additional choices, one per line. +A set of custom choices that will be appended to the base choice set (if any). ### Order Alphabetically diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 332131c7a..c23391023 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -78,13 +78,10 @@ class CustomFieldChoiceSetViewSet(NetBoxModelViewSet): q = q.lower() choices = [c for c in choices if q in c[0].lower() or q in c[1].lower()] - page = self.paginate_queryset(choices) - if page is not None: + # Paginate data + if page := self.paginate_queryset(choices): data = [ - { - 'value': c[0], - 'label': c[1], - } for c in page + {'value': c[0], 'label': c[1]} for c in page ] return self.get_paginated_response(data) diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index 1ab36729e..2b444bbdf 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -73,9 +73,9 @@ class CustomFieldChoiceSetBaseChoices(ChoiceSet): UN_LOCODE = 'UN_LOCODE' CHOICES = ( - (IATA, 'IATA'), - (ISO_3166, 'ISO 3166'), - (UN_LOCODE, 'UN/LOCODE'), + (IATA, 'IATA (Airport codes)'), + (ISO_3166, 'ISO 3166 (Country codes)'), + (UN_LOCODE, 'UN/LOCODE (Location codes)'), ) diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index e3ff2f6ff..9f490ae73 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -66,7 +66,7 @@ class CustomFieldChoiceSetImportForm(CSVModelForm): base_choices = CSVChoiceField( choices=CustomFieldChoiceSetBaseChoices, required=False, - help_text=_('The classification of entry') + help_text=_('The base set of predefined choices to use (if any)') ) class Meta: diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index 26a010af3..d5b132110 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -19,7 +19,6 @@ from utilities.forms.fields import ( CommentField, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, SlugField, ) -from utilities.forms.widgets import ChoicesWidget from virtualization.models import Cluster, ClusterGroup, ClusterType diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 3f3bc820c..0ff218327 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -410,7 +410,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): # Select elif self.type in (CustomFieldTypeChoices.TYPE_SELECT, CustomFieldTypeChoices.TYPE_MULTISELECT): - choices = self.choices + choices = self.choice_set.choices default_choice = self.default if self.default in self.choices else None if not required or default_choice is None: @@ -427,7 +427,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): field_class = CSVMultipleChoiceField if for_csv_import else DynamicMultipleChoiceField widget_class = APISelectMultiple field = field_class( - choices=self.choice_set.choices, + choices=choices, required=required, initial=initial, widget=widget_class(api_url=f'/api/extras/custom-field-choices/{self.choice_set.pk}/choices/') @@ -664,7 +664,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel ) order_alphabetically = models.BooleanField( default=False, - help_text=_('Choices are automatically ordered alphabetically on save') + help_text=_('Choices are automatically ordered alphabetically') ) clone_fields = ('extra_choices', 'order_alphabetically') diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index d9c6b069a..ce69d7f57 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -64,11 +64,9 @@ class CustomFieldTable(NetBoxTable): ) content_types = columns.ContentTypesColumn() required = columns.BooleanColumn() - ui_visibility = columns.ChoiceFieldColumn( - verbose_name="UI visibility" - ) + ui_visibility = columns.ChoiceFieldColumn(verbose_name="UI visibility") description = columns.MarkdownColumn() - choices = columns.ChoiceSetColumn( + choices = columns.ChoicesColumn( max_items=10, orderable=False ) @@ -92,7 +90,7 @@ class CustomFieldChoiceSetTable(NetBoxTable): extra_choices = tables.TemplateColumn( template_code="""{% for k, v in value.items %}{{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}""" ) - choices = columns.ChoiceSetColumn( + choices = columns.ChoicesColumn( max_items=10, orderable=False ) diff --git a/netbox/netbox/tables/columns.py b/netbox/netbox/tables/columns.py index 717fd1569..26c2d1083 100644 --- a/netbox/netbox/tables/columns.py +++ b/netbox/netbox/tables/columns.py @@ -24,7 +24,7 @@ __all__ = ( 'ArrayColumn', 'BooleanColumn', 'ChoiceFieldColumn', - 'ChoiceSetColumn', + 'ChoicesColumn', 'ColorColumn', 'ColoredLabelColumn', 'ContentTypeColumn', @@ -623,7 +623,7 @@ class ArrayColumn(tables.Column): return ', '.join(value) -class ChoiceSetColumn(tables.Column): +class ChoicesColumn(tables.Column): """ Display the human-friendly labels of a set of choices. """ diff --git a/netbox/utilities/forms/widgets/misc.py b/netbox/utilities/forms/widgets/misc.py index ea75ce88e..c4d77fc9a 100644 --- a/netbox/utilities/forms/widgets/misc.py +++ b/netbox/utilities/forms/widgets/misc.py @@ -1,6 +1,7 @@ from django import forms __all__ = ( + 'ArrayWidget', 'ChoicesWidget', 'ClearableFileInput', 'MarkdownWidget', @@ -46,6 +47,16 @@ class SlugWidget(forms.TextInput): template_name = 'widgets/sluginput.html' +class ArrayWidget(forms.Textarea): + """ + Render each item of an array on a new line within a textarea for easy editing/ + """ + def format_value(self, value): + if value is None or not len(value): + return None + return '\n'.join(value) + + class ChoicesWidget(forms.Textarea): """ Render each key-value pair of a dictionary on a new line within a textarea for easy editing.