Skip to content

Commit 36bb99b

Browse files
authored
Fixed QueryArrayWidget.value_from_datadict() to not mutate input data. (#1540)
1 parent ccf9582 commit 36bb99b

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

django_filters/widgets.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class QueryArrayWidget(BaseCSVWidget, forms.TextInput):
246246

247247
def value_from_datadict(self, data, files, name):
248248
if not isinstance(data, MultiValueDict):
249+
data = data.copy()
249250
for key, value in data.items():
250251
# treat value as csv string: ?foo=1,2
251252
if isinstance(value, str):

tests/test_filtering.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from django_filters.filters import (
1515
AllValuesFilter,
1616
AllValuesMultipleFilter,
17+
BaseInFilter,
1718
CharFilter,
1819
ChoiceFilter,
1920
DateFromToRangeFilter,
@@ -31,6 +32,7 @@
3132
TypedMultipleChoiceFilter,
3233
)
3334
from django_filters.filterset import FilterSet
35+
from django_filters.widgets import QueryArrayWidget
3436

3537
from .models import (
3638
STATUS_CHOICES,
@@ -1977,10 +1979,10 @@ class Meta:
19771979

19781980
class MiscFilterSetTests(TestCase):
19791981
def setUp(self):
1980-
User.objects.create(username="alex", status=1)
1981-
User.objects.create(username="jacob", status=2)
1982-
User.objects.create(username="aaron", status=2)
1983-
User.objects.create(username="carl", status=0)
1982+
User.objects.create(username="alex", last_name="johnson", status=1)
1983+
User.objects.create(username="jacob", last_name="johnson", status=2)
1984+
User.objects.create(username="aaron", last_name="white", status=2)
1985+
User.objects.create(username="carl", last_name="black", status=0)
19841986

19851987
def test_filtering_with_declared_filters(self):
19861988
class F(FilterSet):
@@ -2056,3 +2058,36 @@ class Meta:
20562058
f = F({"status": "2"}, queryset=qs)
20572059
self.assertEqual(len(f.qs), 2)
20582060
self.assertEqual(f.qs.count(), 2)
2061+
2062+
def test_filtering_with_widgets(self):
2063+
class CharInFilter(BaseInFilter, CharFilter):
2064+
pass
2065+
2066+
class F(FilterSet):
2067+
last_name = CharInFilter(widget=QueryArrayWidget)
2068+
username = CharInFilter()
2069+
2070+
class Meta:
2071+
model = User
2072+
fields = ["last_name", "username"]
2073+
2074+
qs = User.objects.all()
2075+
2076+
f = F({"last_name": ["johnson"]}, queryset=qs)
2077+
self.assertQuerysetEqual(
2078+
f.qs, ["alex", "jacob"], lambda o: o.username, ordered=False
2079+
)
2080+
2081+
f = F({"last_name": ["johnson"], "username": "carl"}, queryset=qs)
2082+
self.assertQuerysetEqual(f.qs, [], lambda o: o.username, ordered=False)
2083+
2084+
f = F({"last_name": ["johnson"], "username": "jacob"}, queryset=qs)
2085+
self.assertQuerysetEqual(f.qs, ["jacob"], lambda o: o.username, ordered=False)
2086+
2087+
f = F(
2088+
{"last_name": ["johnson", "white"], "username": "jacob, carl, aaron"},
2089+
queryset=qs,
2090+
)
2091+
self.assertQuerysetEqual(
2092+
f.qs, ["jacob", "aaron"], lambda o: o.username, ordered=False
2093+
)

0 commit comments

Comments
 (0)