Skip to content

Commit

Permalink
Fixed QueryArrayWidget.value_from_datadict() to not mutate input data. (
Browse files Browse the repository at this point in the history
  • Loading branch information
legau authored Mar 26, 2023
1 parent ccf9582 commit 36bb99b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
1 change: 1 addition & 0 deletions django_filters/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
43 changes: 39 additions & 4 deletions tests/test_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from django_filters.filters import (
AllValuesFilter,
AllValuesMultipleFilter,
BaseInFilter,
CharFilter,
ChoiceFilter,
DateFromToRangeFilter,
Expand All @@ -31,6 +32,7 @@
TypedMultipleChoiceFilter,
)
from django_filters.filterset import FilterSet
from django_filters.widgets import QueryArrayWidget

from .models import (
STATUS_CHOICES,
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -2056,3 +2058,36 @@ 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
)

0 comments on commit 36bb99b

Please sign in to comment.