假设模型管理员具有:
search_fields = ("^name", "=kind")
如果name
为"Leonardo Da Vinci"
,则可以使用查询Leon
或Leonardo
找到它,但不能找到Leonardo Da
或Leonardo Da Vinci
。如果是kind
,例如"polymath genius"
,无法在任何查询中找到此类值。理想情况下,人们可以发布"multiple words" "Leonardo Da"
并获得此记录;但鉴于Django如何分割查询,它并没有做到人们所期望的。
9年前this ticket显然提出了这个问题并解决了。然后Django被重写了,显然这已经被丢弃了。
有没有人知道这是否可行?我可能以为我需要覆盖ModelAdmin.get_search_results
......还有什么更优雅的吗?
答案 0 :(得分:0)
这是我能想到的最好的。我真的不喜欢它,因为如果Django更新它看起来可能会失败。它有很多复制意大利面,基本上只是换一行(for bit in search_term.split():
)
from django.utils.text import smart_split, unescape_string_literal
from django.db import models
from functools import reduce
import operator
from django.contrib.admin.utils import lookup_needs_distinct
class QuotedSearchModelAdmin(admin.ModelAdmin):
def get_search_results(self, request, queryset, search_term):
"""
Returns a tuple containing a queryset to implement the search,
and a boolean indicating if the results may contain duplicates.
"""
# Apply keyword searches.
def construct_search(field_name):
if field_name.startswith('^'):
return "%s__istartswith" % field_name[1:]
elif field_name.startswith('='):
return "%s__iexact" % field_name[1:]
elif field_name.startswith('@'):
return "%s__search" % field_name[1:]
else:
return "%s__icontains" % field_name
# Group using quotes
def unescape_string_literal_if_possible(bit):
try:
return unescape_string_literal(bit)
except ValueError:
return bit
use_distinct = False
search_fields = self.get_search_fields(request)
if search_fields and search_term:
orm_lookups = [construct_search(str(search_field))
for search_field in search_fields]
search_term_list = [unescape_string_literal_if_possible(bit)
for bit in smart_split(search_term)]
for bit in search_term_list:
or_queries = [models.Q(**{orm_lookup: bit})
for orm_lookup in orm_lookups]
queryset = queryset.filter(reduce(operator.or_, or_queries))
if not use_distinct:
for search_spec in orm_lookups:
if lookup_needs_distinct(self.opts, search_spec):
use_distinct = True
break
return queryset, use_distinct