Просмотр исходного кода

Merge pull request #7206 from netbox-community/7205-applied-filters

Handle `null_option` in `applied_filters` template tag
Jeremy Stretch 4 лет назад
Родитель
Сommit
26ceeb61ef

+ 1 - 0
docs/release-notes/version-3.0.md

@@ -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
 
 ---

+ 10 - 0
netbox/utilities/forms/fields.py

@@ -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)

+ 12 - 4
netbox/utilities/forms/utils.py

@@ -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
@@ -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.