Fix SearchFilter to-many behavior by ANDing cond's

This commit is contained in:
Ryan P Kilby 2017-07-10 14:24:58 -04:00
parent f02b7f1329
commit d1cfec8d87
2 changed files with 7 additions and 1 deletions

View File

@ -140,12 +140,14 @@ class SearchFilter(BaseFilterBackend):
] ]
base = queryset base = queryset
conditions = []
for search_term in search_terms: for search_term in search_terms:
queries = [ queries = [
models.Q(**{orm_lookup: search_term}) models.Q(**{orm_lookup: search_term})
for orm_lookup in orm_lookups for orm_lookup in orm_lookups
] ]
queryset = queryset.filter(reduce(operator.or_, queries)) conditions.append(reduce(operator.or_, queries))
queryset = queryset.filter(reduce(operator.and_, conditions))
if self.must_call_distinct(queryset, search_fields): if self.must_call_distinct(queryset, search_fields):
# Filtering against a many-to-many field requires us to # Filtering against a many-to-many field requires us to

View File

@ -5,6 +5,7 @@ import unittest
import warnings import warnings
from decimal import Decimal from decimal import Decimal
import django
import pytest import pytest
from django.conf.urls import url from django.conf.urls import url
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
@ -668,12 +669,15 @@ class SearchFilterToManyTests(TestCase):
b1 = Blog.objects.create(name='Blog 1') b1 = Blog.objects.create(name='Blog 1')
b2 = Blog.objects.create(name='Blog 2') b2 = Blog.objects.create(name='Blog 2')
# Multiple entries on Lennon published in 1979 - distinct should deduplicate
Entry.objects.create(blog=b1, headline='Something about Lennon', pub_date=datetime.date(1979, 1, 1)) Entry.objects.create(blog=b1, headline='Something about Lennon', pub_date=datetime.date(1979, 1, 1))
Entry.objects.create(blog=b1, headline='Another thing about Lennon', pub_date=datetime.date(1979, 6, 1)) Entry.objects.create(blog=b1, headline='Another thing about Lennon', pub_date=datetime.date(1979, 6, 1))
# Entry on Lennon *and* a separate entry in 1979 - should not match
Entry.objects.create(blog=b2, headline='Something unrelated', pub_date=datetime.date(1979, 1, 1)) Entry.objects.create(blog=b2, headline='Something unrelated', pub_date=datetime.date(1979, 1, 1))
Entry.objects.create(blog=b2, headline='Retrospective on Lennon', pub_date=datetime.date(1990, 6, 1)) Entry.objects.create(blog=b2, headline='Retrospective on Lennon', pub_date=datetime.date(1990, 6, 1))
@unittest.skipIf(django.VERSION < (1, 9), "Django 1.8 does not support transforms")
def test_multiple_filter_conditions(self): def test_multiple_filter_conditions(self):
class SearchListView(generics.ListAPIView): class SearchListView(generics.ListAPIView):
queryset = Blog.objects.all() queryset = Blog.objects.all()