mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-17 09:12:18 -06:00
Fixes #21160: Fix performance issue rendering FilterSet forms w/ large choicesets (#21200)
Some checks failed
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CI / build (20.x, 3.14) (push) Waiting to run
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Some checks failed
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CI / build (20.x, 3.14) (push) Waiting to run
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from utilities.forms.widgets.apiselect import APISelect, APISelectMultiple
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'FilterModifierWidget',
|
'FilterModifierWidget',
|
||||||
'MODIFIER_EMPTY_FALSE',
|
'MODIFIER_EMPTY_FALSE',
|
||||||
@@ -94,9 +96,37 @@ class FilterModifierWidget(forms.Widget):
|
|||||||
# to the original widget before rendering
|
# to the original widget before rendering
|
||||||
self.original_widget.attrs.update(self.attrs)
|
self.original_widget.attrs.update(self.attrs)
|
||||||
|
|
||||||
|
# For APISelect/APISelectMultiple widgets, temporarily clear choices to prevent queryset evaluation
|
||||||
|
original_choices = None
|
||||||
|
if isinstance(self.original_widget, (APISelect, APISelectMultiple)):
|
||||||
|
original_choices = self.original_widget.choices
|
||||||
|
|
||||||
|
# Only keep selected choices to preserve current selection in HTML
|
||||||
|
if value:
|
||||||
|
values = value if isinstance(value, (list, tuple)) else [value]
|
||||||
|
|
||||||
|
if hasattr(original_choices, 'queryset'):
|
||||||
|
queryset = original_choices.queryset
|
||||||
|
selected_objects = queryset.filter(pk__in=values)
|
||||||
|
# Build minimal choice list with just the selected values
|
||||||
|
self.original_widget.choices = [
|
||||||
|
(obj.pk, str(obj)) for obj in selected_objects
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.original_widget.choices = [
|
||||||
|
choice for choice in original_choices if choice[0] in values
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# No selection - render empty select element
|
||||||
|
self.original_widget.choices = []
|
||||||
|
|
||||||
# Get context from the original widget
|
# Get context from the original widget
|
||||||
original_context = self.original_widget.get_context(name, value, attrs)
|
original_context = self.original_widget.get_context(name, value, attrs)
|
||||||
|
|
||||||
|
# Restore original choices if we modified them
|
||||||
|
if original_choices is not None:
|
||||||
|
self.original_widget.choices = original_choices
|
||||||
|
|
||||||
# Build our wrapper context
|
# Build our wrapper context
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
context['widget']['original_widget'] = original_context['widget']
|
context['widget']['original_widget'] = original_context['widget']
|
||||||
|
|||||||
Reference in New Issue
Block a user