From 35ec5b4bc4e12ddedf4450f4a5efee5ed118a64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9ni=20Gauffier?= Date: Sun, 26 Mar 2023 11:30:50 +0200 Subject: [PATCH] Fixed QueryArrayWidget.value_from_datadict() to not mutate input data. --- django_filters/widgets.py | 1 + tests/test_filtering.py | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/django_filters/widgets.py b/django_filters/widgets.py index 49afd2af5..fe99fec93 100644 --- a/django_filters/widgets.py +++ b/django_filters/widgets.py @@ -246,6 +246,7 @@ class QueryArrayWidget(BaseCSVWidget, forms.TextInput): def value_from_datadict(self, data, files, name): if not isinstance(data, MultiValueDict): + data = data.copy() for key, value in data.items(): # treat value as csv string: ?foo=1,2 if isinstance(value, str): diff --git a/tests/test_filtering.py b/tests/test_filtering.py index 8b8f010a3..f027742aa 100644 --- a/tests/test_filtering.py +++ b/tests/test_filtering.py @@ -14,6 +14,7 @@ from django_filters.filters import ( AllValuesFilter, AllValuesMultipleFilter, + BaseInFilter, CharFilter, ChoiceFilter, DateFromToRangeFilter, @@ -31,6 +32,7 @@ TypedMultipleChoiceFilter, ) from django_filters.filterset import FilterSet +from django_filters.widgets import QueryArrayWidget from .models import ( STATUS_CHOICES, @@ -1977,10 +1979,10 @@ class Meta: class MiscFilterSetTests(TestCase): def setUp(self): - User.objects.create(username="alex", status=1) - User.objects.create(username="jacob", status=2) - User.objects.create(username="aaron", status=2) - User.objects.create(username="carl", status=0) + User.objects.create(username="alex", last_name="johnson", status=1) + User.objects.create(username="jacob", last_name="johnson", status=2) + User.objects.create(username="aaron", last_name="white", status=2) + User.objects.create(username="carl", last_name="black", status=0) def test_filtering_with_declared_filters(self): class F(FilterSet): @@ -2056,3 +2058,30 @@ class Meta: f = F({"status": "2"}, queryset=qs) self.assertEqual(len(f.qs), 2) self.assertEqual(f.qs.count(), 2) + + def test_filtering_with_widgets(self): + + class CharInFilter(BaseInFilter, CharFilter): + pass + + class F(FilterSet): + last_name = CharInFilter(widget=QueryArrayWidget) + username = CharInFilter() + + class Meta: + model = User + fields = ["last_name", "username"] + + qs = User.objects.all() + + f = F({"last_name": ["johnson"]}, queryset=qs) + self.assertQuerysetEqual(f.qs, ["alex", "jacob"], lambda o: o.username, ordered=False) + + f = F({"last_name": ["johnson"], "username": "carl"}, queryset=qs) + self.assertQuerysetEqual(f.qs, [], lambda o: o.username, ordered=False) + + f = F({"last_name": ["johnson"], "username": "jacob"}, queryset=qs) + self.assertQuerysetEqual(f.qs, ["jacob"], lambda o: o.username, ordered=False) + + f = F({"last_name": ["johnson", "white"], "username": "jacob, carl, aaron"}, queryset=qs) + self.assertQuerysetEqual(f.qs, ["jacob", "aaron"], lambda o: o.username, ordered=False)