From 04ee55a40cc25ed09238c538f2eb5b7b8dfa4858 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 21 Feb 2020 21:38:25 -0500 Subject: [PATCH] Fixes #4240: Fix exception when filtering foreign keys by NULL --- docs/release-notes/version-2.7.md | 1 + netbox/utilities/forms.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index 26ba370bd..be45c9846 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -11,6 +11,7 @@ * [#4232](https://github.com/netbox-community/netbox/issues/4232) - Enforce consistent background striping in rack elevations * [#4235](https://github.com/netbox-community/netbox/issues/4235) - Fix API representation of `content_type` for export templates * [#4239](https://github.com/netbox-community/netbox/issues/4239) - Fix exception when selecting all filtered objects during bulk edit +* [#4240](https://github.com/netbox-community/netbox/issues/4240) - Fix exception when filtering foreign keys by NULL --- diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index a7ee63eaa..71c262cdc 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -2,8 +2,9 @@ import csv import json import re from io import StringIO -import yaml +import django_filters +import yaml from django import forms from django.conf import settings from django.contrib.postgres.forms.jsonb import JSONField as _JSONField, InvalidJSONInput @@ -564,18 +565,17 @@ class TagFilterField(forms.MultipleChoiceField): class DynamicModelChoiceMixin: - field_modifier = '' + filter = django_filters.ModelChoiceFilter def get_bound_field(self, form, field_name): bound_field = BoundField(form, self, field_name) # Modify the QuerySet of the field before we return it. Limit choices to any data already bound: Options # will be populated on-demand via the APISelect widget. - field_name = '{}{}'.format(self.to_field_name or 'pk', self.field_modifier) - if bound_field.data: - self.queryset = self.queryset.filter(**{field_name: self.prepare_value(bound_field.data)}) - elif bound_field.initial: - self.queryset = self.queryset.filter(**{field_name: self.prepare_value(bound_field.initial)}) + data = bound_field.data or bound_field.initial + if data: + filter = self.filter(field_name=self.to_field_name or 'pk', queryset=self.queryset) + self.queryset = filter.filter(self.queryset, data) else: self.queryset = self.queryset.none() @@ -594,7 +594,7 @@ class DynamicModelMultipleChoiceField(DynamicModelChoiceMixin, forms.ModelMultip """ A multiple-choice version of DynamicModelChoiceField. """ - field_modifier = '__in' + filter = django_filters.ModelMultipleChoiceFilter class LaxURLField(forms.URLField):