Django admin搜索带有^和=运算符的多单词短语

2024-05-23 16:04:20 发布

您现在位置:Python中文网/ 问答频道 /正文

假设模型管理员拥有:

search_fields = ("^name", "=kind")

如果name"Leonardo Da Vinci",则可以使用查询Leon或{},但不能使用Leonardo Da或{}。如果kind"polymath genius",那么在任何查询中都找不到这样的值。理想情况下,可以发布"multiple words" "Leonardo Da"并获得此记录;但是考虑到Django如何分割查询,它并没有达到预期的效果。在

这个问题显然是9年前在this ticket中提出并解决的。然后Django被重写了,很明显这个被丢在了某个地方。在

有人知道这是否可能吗?我可能想我需要重写ModelAdmin.get_search_results。。。还有更优雅的吗?在


Tags: djangoname模型fieldssearch管理员情况da
1条回答
网友
1楼 · 发布于 2024-05-23 16:04:20

这是我能想到的最好的。我真的不喜欢它,因为如果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

相关问题 更多 >