|
1 |
| -from functools import partial, partialmethod |
| 1 | +import operator |
| 2 | +from functools import partial, partialmethod, reduce |
2 | 3 |
|
3 | 4 | from django import forms
|
4 | 5 | from django.apps import apps
|
5 | 6 | from django.conf import settings
|
6 | 7 | from django.contrib.admin import helpers, widgets
|
7 | 8 | from django.contrib.admin.exceptions import DisallowedModelAdminToField
|
8 |
| -from django.contrib.admin.options import IS_POPUP_VAR, TO_FIELD_VAR, csrf_protect_m, get_ul_class |
| 9 | +from django.contrib.admin.options import ( |
| 10 | + IS_POPUP_VAR, |
| 11 | + TO_FIELD_VAR, |
| 12 | + csrf_protect_m, |
| 13 | + get_ul_class, |
| 14 | +) |
9 | 15 | from django.contrib.admin.utils import flatten_fieldsets, get_deleted_objects, unquote
|
10 | 16 | from django.core.exceptions import PermissionDenied
|
11 | 17 | from django.forms.formsets import all_valid
|
|
18 | 24 | from django.utils.html import escape
|
19 | 25 | from django.utils.text import capfirst
|
20 | 26 | from django.utils.translation import gettext as _
|
| 27 | +from mongoengine import Q |
21 | 28 |
|
22 |
| -from django_mongoengine.fields import EmbeddedDocumentField, ListField, ReferenceField, StringField |
| 29 | +from django_mongoengine.fields import ( |
| 30 | + EmbeddedDocumentField, |
| 31 | + ListField, |
| 32 | + ReferenceField, |
| 33 | + StringField, |
| 34 | +) |
23 | 35 | from django_mongoengine.forms.documents import (
|
24 | 36 | BaseInlineDocumentFormSet,
|
25 | 37 | DocumentForm,
|
@@ -234,6 +246,36 @@ def get_changelist_formset(self, request, **kwargs):
|
234 | 246 | **defaults
|
235 | 247 | )
|
236 | 248 |
|
| 249 | + def get_search_results(self, request, queryset, search_term): |
| 250 | + """ |
| 251 | + Return a tuple containing a queryset to implement the search |
| 252 | + and a boolean indicating if the results may contain duplicates. |
| 253 | + """ |
| 254 | + |
| 255 | + def construct_search(field_name): |
| 256 | + if field_name.startswith('^'): |
| 257 | + return "%s__istartswith" % field_name[1:] |
| 258 | + elif field_name.startswith('='): |
| 259 | + return "%s__iexact" % field_name[1:] |
| 260 | + # No __search for mongoengine |
| 261 | + # elif field_name.startswith('@'): |
| 262 | + # return "%s__search" % field_name[1:] |
| 263 | + else: |
| 264 | + return "%s__icontains" % field_name |
| 265 | + |
| 266 | + search_fields = self.get_search_fields(request) |
| 267 | + |
| 268 | + if search_fields and search_term: |
| 269 | + orm_lookups = [ |
| 270 | + construct_search(str(search_field)) for search_field in search_fields |
| 271 | + ] |
| 272 | + for bit in search_term.split(): |
| 273 | + or_queries = [Q(**{orm_lookup: bit}) for orm_lookup in orm_lookups] |
| 274 | + queryset = queryset.filter(reduce(operator.or_, or_queries)) |
| 275 | + |
| 276 | + return queryset, False |
| 277 | + |
| 278 | + |
237 | 279 | def get_changelist(self, request, **kwargs):
|
238 | 280 | """
|
239 | 281 | Returns the ChangeList class for use on the changelist page.
|
|
0 commit comments