Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 05556e1

Browse files
Resolve #39 -- Make default search more like Django admin
Different to before we now match search terms only if all bits match or the entire statement. The last part differs from the behavior in Django admin, which does not inlcude exact machtes of the entire search term inlcude spaces. Partially revert 07054b2
1 parent c093aab commit 05556e1

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed

‎django_select2/forms.py‎

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@
4646
:parts: 1
4747
4848
"""
49-
import re
49+
import operator
5050
import uuid
51+
from functools import reduce
5152
from itertools import chain
5253
from pickle import PicklingError # nosec
5354

5455
from django import forms
56+
from django.contrib.admin.utils import lookup_needs_distinct
5557
from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
5658
from django.core import signing
5759
from django.db.models import Q
@@ -315,8 +317,6 @@ class HeavySelect2TagWidget(HeavySelect2Mixin, Select2TagWidget):
315317
class ModelSelect2Mixin:
316318
"""Widget mixin that provides attributes and methods for :class:`.AutoResponseView`."""
317319

318-
_word_split_pattern = re.compile(r"\t|\n| ")
319-
320320
model = None
321321
queryset = None
322322
search_fields = []
@@ -400,19 +400,24 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
400400
search_fields = self.get_search_fields()
401401
select = Q()
402402

403-
if term != "":
404-
for field in search_fields:
405-
field_select = Q(**{field: term})
406-
if "contains" in field:
407-
for word in filter(None, self._word_split_pattern.split(term)):
408-
field_select |= Q(**{field: word})
409-
410-
select |= field_select
403+
use_distinct = False
404+
if search_fields and term:
405+
for bit in term.split():
406+
or_queries = [Q(**{orm_lookup: bit}) for orm_lookup in search_fields]
407+
select &= reduce(operator.or_, or_queries)
408+
or_queries = [Q(**{orm_lookup: term}) for orm_lookup in search_fields]
409+
select |= reduce(operator.or_, or_queries)
410+
use_distinct |= any(
411+
lookup_needs_distinct(queryset.model._meta, search_spec)
412+
for search_spec in search_fields
413+
)
411414

412415
if dependent_fields:
413416
select &= Q(**dependent_fields)
414417

415-
return queryset.filter(select).distinct()
418+
if use_distinct:
419+
queryset.filter(select).distinct()
420+
return queryset.filter(select)
416421

417422
def get_queryset(self):
418423
"""

‎tests/test_forms.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ def test_filter_queryset__contains(self, genres):
482482
assert qs.exists()
483483

484484
qs = widget.filter_queryset(None, "NOT Gen")
485-
assert qs.exists(), "contains works even if only one part matches"
485+
assert notqs.exists(), "contains works even if all bits match"
486486

487487
def test_filter_queryset__multiple_fields(self, genres):
488488
genre = Genre.objects.create(title="Space Genre")

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /