|
46 | 46 | :parts: 1 |
47 | 47 |
|
48 | 48 | """ |
49 | | -import re |
| 49 | +import operator |
50 | 50 | import uuid |
| 51 | +from functools import reduce |
51 | 52 | from itertools import chain |
52 | 53 | from pickle import PicklingError # nosec |
53 | 54 |
|
54 | 55 | from django import forms |
| 56 | +from django.contrib.admin.utils import lookup_needs_distinct |
55 | 57 | from django.contrib.admin.widgets import SELECT2_TRANSLATIONS |
56 | 58 | from django.core import signing |
57 | 59 | from django.db.models import Q |
@@ -315,8 +317,6 @@ class HeavySelect2TagWidget(HeavySelect2Mixin, Select2TagWidget): |
315 | 317 | class ModelSelect2Mixin: |
316 | 318 | """Widget mixin that provides attributes and methods for :class:`.AutoResponseView`.""" |
317 | 319 |
|
318 | | - _word_split_pattern = re.compile(r"\t|\n| ") |
319 | | - |
320 | 320 | model = None |
321 | 321 | queryset = None |
322 | 322 | search_fields = [] |
@@ -400,19 +400,24 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields): |
400 | 400 | search_fields = self.get_search_fields() |
401 | 401 | select = Q() |
402 | 402 |
|
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 | + ) |
411 | 414 |
|
412 | 415 | if dependent_fields: |
413 | 416 | select &= Q(**dependent_fields) |
414 | 417 |
|
415 | | - return queryset.filter(select).distinct() |
| 418 | + if use_distinct: |
| 419 | + queryset.filter(select).distinct() |
| 420 | + return queryset.filter(select) |
416 | 421 |
|
417 | 422 | def get_queryset(self): |
418 | 423 | """ |
|
0 commit comments