如何拆分用户在 Django 应用程序的输入字段中插入的单词

how to split words that user inserts in input field in Django app

我有一个搜索栏,正在搜索 2 个模型列标题,body,short_description。我am.usingMySQL数据库。现在,我正在使用 Q 查询,但我想 'improve'.

有一些搜索限制

其中之一是 Q 查找仅基于与字段中完全相同的短语结果查找结果,例如,我有标题 why python is so amazing?,我必须写 whypythonpython is 以获得结果。我想要的是扩展搜索栏以按以下方式工作:

用户在搜索栏中插入一个问题:python language 并且搜索查找拆分每个单词并 returning 所有 object 包含 pythonlanguage。最后,无论用户输入 python language 还是 amazing python.

,结果都是 return object 和 why python is so amazing?

我在下面发布我当前的代码:

views.py

def search_items(request):
    query = request.GET.get('q')
    article_list= Article.objects.filter(title__icontains=query)
    qa_list = QA.objects.filter(title__icontains=query)

    if query is not None:
        lookups = Q(title__icontains=query) | Q(short_description__icontains=query) | Q(body__icontains=query)
        article_list= Article.objects.filter(lookups, status=1).distinct()
        qa_list = QA.objects.filter(lookups, status=1).distinct()

    context = {
        'query_name': query,
        'article_list': article_list,
        'qa_list': qa_list,
    }
    return render(request, 'search/search_items.html', context)

我检查了这个 solution and this one 但结果并不令人满意,因为当我输入 python language 来查找标题为 why python is so amazing 的 object 时,我没有得到任何结果.

问题

对于如何获得 objects 的结果以及基于用户在输入字段中输入的单词的所有 objects 的列表,我将不胜感激。

我 运行 遇到了同样的问题,并通过在我的模型上方的 models.py 中添加自定义搜索管理器解决了这个问题。管理器有两种方法,一种用于单词搜索,另一种用于multi-word。使用下面的 .split() 将查询字符串拆分为单词列表(参见视图)。

models.py

class MyModelSearchManager(models.QuerySet):
    def search(self, query=None):
        qs = self
        if query is not None:
            or_lookup = (Q(some_field__icontains=query))
            qs = qs.filter(or_lookup).distinct()
        return qs

    def search_and(self, query=None):
        qs = self
        if query is not None:
            or_lookup = reduce(lambda x, y: x & y, [Q(some_field__icontains=word) for word in query])
            qs = qs.filter(or_lookup).distinct()
        return qs

class MyModelManager(models.Manager):
    def get_queryset(self):
        return MyModelSearchManager(self.model, using=self._db)

    def search(self, query=None):
        return self.get_queryset().search(query=query)

    def search_and(self, query=None):
        return self.get_queryset().search_and(query=query)

当然,在您的模型字段下方声明自定义管理器:

objects = MyModelManager()

然后,在您看来,拆分搜索字符串并区分单词搜索和 multi-word 搜索:

class SearchView(ListView):
    template_name = 'my_app_templates/search_results.html'
    count = 0
    
    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['count'] = self.count or 0
        context['query'] = self.request.GET.get('q')
        return context

    def get_queryset(self):
        request = self.request
        query_list = request.GET.get('q', None).split()
        query_list_count = len(query_list)
        
        if query_list is not None:
            if query_list_count == 1:
                qs = MyModel.objects.search(query=query_list[0]).order_by('-date_added')
                self.count = len(qs)
            elif query_list_count > 1:
                qs = MyModel.objects.search_and(query=query_list).order_by('-date_added')
                self.count = len(qs)
            result_count = len(qs)
            create_search_record(self, request, query_list, query_list_count, result_count)
            return qs

对于 multi-word 字符串,神奇之处在于 reduce 函数,该函数针对给定的模型字段尝试所有关键字。这种经理模式的大部分功劳归功于 Justin Mitchel 的 excellent writeup on multi-model search.