Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions docs/release-notes/version-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* [#7188](https://github.com/netbox-community/netbox/issues/7188) - Fix issue where select fields with `null_option` did not render or send the null option
* [#7189](https://github.com/netbox-community/netbox/issues/7189) - Set connection factory for django-redis when Sentinel is in use
* [#7193](https://github.com/netbox-community/netbox/issues/7193) - Fix prefix (flat) template issue when viewing child prefixes with prefixes available
* [#7205](https://github.com/netbox-community/netbox/issues/7205) - Fix issue where selected fields with `null_option` set were not added to applied filters
* [#7209](https://github.com/netbox-community/netbox/issues/7209) - Allow unlimited API results when `MAX_PAGE_SIZE` is disabled

---
Expand Down
10 changes: 10 additions & 0 deletions netbox/utilities/forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,3 +477,13 @@ class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultip
"""
filter = django_filters.ModelMultipleChoiceFilter
widget = widgets.APISelectMultiple

def clean(self, value):
"""
When null option is enabled and "None" is sent as part of a form to be submitted, it is sent as the
string 'null'. This will check for that condition and gracefully handle the conversion to a NoneType.
"""
if self.null_option is not None and settings.FILTERS_NULL_CHOICE_VALUE in value:
value = [v for v in value if v != settings.FILTERS_NULL_CHOICE_VALUE]
return [None, *value]
return super().clean(value)
16 changes: 12 additions & 4 deletions netbox/utilities/forms/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re

from django import forms
from django.conf import settings
from django.forms.models import fields_for_model

from utilities.choices import unpack_grouped_choices
Expand Down Expand Up @@ -120,13 +121,20 @@ def get_selected_values(form, field_name):
if not hasattr(form, 'cleaned_data'):
form.is_valid()
filter_data = form.cleaned_data.get(field_name)

field = form.fields[field_name]
# Selection field
if hasattr(form.fields[field_name], 'choices'):
if hasattr(field, 'choices'):
try:
choices = dict(unpack_grouped_choices(form.fields[field_name].choices))
choices = unpack_grouped_choices(field.choices)

if hasattr(field, 'null_option'):
# If the field has a `null_option` attribute set and it is selected,
# add it to the field's grouped choices.
if field.null_option is not None and None in filter_data:
choices.append((settings.FILTERS_NULL_CHOICE_VALUE, field.null_option))

return [
label for value, label in choices.items() if str(value) in filter_data
label for value, label in choices if str(value) in filter_data or None in filter_data
]
except TypeError:
# Field uses dynamic choices. Show all that have been populated.
Expand Down