Skip to content

Closes #12194: Add pre-defined custom field choices #13219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
70e1e11
Initial work on custom field choice sets
jeremystretch Jul 17, 2023
f3bfe29
Rename choices to extra_choices (prep for #12194)
jeremystretch Jul 17, 2023
42a9407
Remove CustomField.choices
jeremystretch Jul 17, 2023
a32992e
Add & update tests
jeremystretch Jul 17, 2023
9f3ffb7
Clean up table columns
jeremystretch Jul 17, 2023
9aff7e7
Add order_alphanetically boolean for choice sets
jeremystretch Jul 17, 2023
1f5b583
Introduce ArrayColumn for choice lists
jeremystretch Jul 17, 2023
feedf51
Show dependent custom fields on choice set view
jeremystretch Jul 17, 2023
00096cc
Update custom fields documentation
jeremystretch Jul 17, 2023
ed2d78f
Introduce ArrayWidget for more convenient editing of choices
jeremystretch Jul 17, 2023
3fa7350
Incorporate PR feedback
jeremystretch Jul 19, 2023
306cfee
Misc cleanup
jeremystretch Jul 19, 2023
b8cf15a
Initial work on predefined choices for custom fields
jeremystretch Jul 18, 2023
4a271df
Merge branch 'feature' into 12194-custom-field-locations
jeremystretch Jul 19, 2023
4dfeb2d
Misc cleanup
jeremystretch Jul 19, 2023
5b570d6
Add IATA airport codes
jeremystretch Jul 19, 2023
c60aec2
#13241: Add support for custom field choice labels
jeremystretch Jul 26, 2023
9f93c02
Restore ArrayColumn
jeremystretch Jul 26, 2023
d8da99f
Misc cleanup
jeremystretch Jul 27, 2023
766b576
Change extra_choices back to a nested ArrayField to preserve choice o…
jeremystretch Jul 27, 2023
94acb10
Merge branch 'feature' into 12194-custom-field-locations
jeremystretch Jul 27, 2023
4ea1598
Hack to bypass GraphQL API test utility absent support for nested Arr…
jeremystretch Jul 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions docs/models/extras/customfieldchoiceset.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
# 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

### Name

The human-friendly name of the choice set.

### Base Choices

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

The list of valid choices, entered as a comma-separated list.
A set of custom choices that will be appended to the base choice set (if any).

### Order Alphabetically

Expand Down
8 changes: 6 additions & 2 deletions netbox/extras/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,16 @@ def get_data_type(self, obj):

class CustomFieldChoiceSetSerializer(ValidatedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='extras-api:customfieldchoiceset-detail')
base_choices = ChoiceField(
choices=CustomFieldChoiceSetBaseChoices,
required=False
)

class Meta:
model = CustomFieldChoiceSet
fields = [
'id', 'url', 'display', 'name', 'description', 'extra_choices', 'order_alphabetically', 'choices_count',
'created', 'last_updated',
'id', 'url', 'display', 'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically',
'choices_count', 'created', 'last_updated',
]


Expand Down
21 changes: 21 additions & 0 deletions netbox/extras/api/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.contenttypes.models import ContentType
from django.http import Http404
from django.shortcuts import get_object_or_404
from django_rq.queues import get_connection
from rest_framework import status
from rest_framework.decorators import action
Expand Down Expand Up @@ -64,6 +65,26 @@ class CustomFieldChoiceSetViewSet(NetBoxModelViewSet):
serializer_class = serializers.CustomFieldChoiceSetSerializer
filterset_class = filtersets.CustomFieldChoiceSetFilterSet

@action(detail=True)
def choices(self, request, pk):
"""
Provides an endpoint to iterate through each choice in a set.
"""
choiceset = get_object_or_404(self.queryset, pk=pk)
choices = choiceset.choices

# Enable filtering
if q := request.GET.get('q'):
q = q.lower()
choices = [c for c in choices if q in c[0].lower() or q in c[1].lower()]

# Paginate data
if page := self.paginate_queryset(choices):
data = [
{'value': c[0], 'label': c[1]} for c in page
]
return self.get_paginated_response(data)


#
# Custom links
Expand Down
13 changes: 13 additions & 0 deletions netbox/extras/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,19 @@ class CustomFieldVisibilityChoices(ChoiceSet):
)


class CustomFieldChoiceSetBaseChoices(ChoiceSet):

IATA = 'IATA'
ISO_3166 = 'ISO_3166'
UN_LOCODE = 'UN_LOCODE'

CHOICES = (
(IATA, 'IATA (Airport codes)'),
(ISO_3166, 'ISO 3166 (Country codes)'),
(UN_LOCODE, 'UN/LOCODE (Location codes)'),
)


#
# CustomLinks
#
Expand Down
9 changes: 9 additions & 0 deletions netbox/extras/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .iata import IATA
from .iso_3166 import ISO_3166
from .un_locode import UN_LOCODE

CHOICE_SETS = {
'IATA': IATA,
'ISO_3166': ISO_3166,
'UN_LOCODE': UN_LOCODE,
}
Loading