如何使用Django.db.models Q模块查询多行用户输入文本数据

Posted

技术标签:

【中文标题】如何使用Django.db.models Q模块查询多行用户输入文本数据【英文标题】:How can I use Django.db.models Q module to query multiple lines of user input text data 【发布时间】:2018-11-27 13:47:25 【问题描述】:

我将如何使用 django.db.models Q 模块使用<textarea> html 输入字段从数据列表中查询多行输入?我可以使用普通的 html <input> 字段很好地查询单个对象。我尝试使用与输入字段相同的代码,除了在请求输入数据时,我尝试像这样拆分行:

  def search_list(request):
    template = 'search_result.html'
    query = request.GET.get('q').split('\n')
    for each in query:
        if each:
            results = Product.objects.filter(Q(name__icontains=each))

这当然行不通。我查询一行数据的代码(有效)是这样的:

  def search(request):
    template = 'search_result.html'
    query = request.GET.get('q')
    if query:
        results = Product.objects.filter(Q(name__icontains=query))

我基本上只是想在我的数据库中搜索用户输入到列表中的数据列表,并通过一个查询返回所有这些结果。您的帮助将不胜感激。谢谢。

【问题讨论】:

应该是 and 还是 or 逻辑:任何元素是否足够,或者文本是否应该包含 all ? 如果没有给出这样的查询应该怎么办? @WillemVanOnsem 应该是“或”逻辑。它应该匹配我数据库中每行文本的名称/短语中存在的任何单词并返回结果。如果没有给出查询,或者给出了不正确的查询,我将在页面上显示与每一行匹配的所有查询,并用某种类型的错误消息代替无效查询。如果我没有正确回答您的问题,请告诉我。 【参考方案1】:

根据您的 cmets,您希望为给定的 q 字符串实现 OR-逻辑。

我们可以通过reduce 来创建这样的Q 对象——创建一个Q 对象列表,每个对象都指定一个Q(name__icontains=...) 约束。我们用“逻辑或”(Python | 中的管道)来减少它,例如:

from django.db.models import Q
from functools import reduce
from operator import or_

def search_list(request):
    template = 'search_result.html'
    results = Product.objects.all()
    error = None
    query = request.GET.get('q')
    if query:
        query = query.split('\n')
    else:
        error = 'No query specified'
    if query:
        results = results.filter(
            reduce(or_, (Q(name__icontains=itm.strip()) for itm in query))
        )
    elif not error:
        error = 'Empty query'
    some_context = 
        'results' : results,
        'error': error
    
    return render(request, 'app/some_template.html', some_context)

因此,我们首先检查q 是否存在并且不是空字符串。如果是这种情况,则错误为'No query specified'。如果有查询,我们拆分该查询,接下来我们检查查询中是否至少有一个元素。如果不是,我们的错误是 'Empty query'(请注意,普通的 .split('\n') 可能不会发生这种情况,但也许你对列表进行后处理,例如删除空元素)。

如果query中有元素,我们执行reduce(..)函数,从而过滤Products。

最后,我们返回一个带有some_template.htmlrender(..)ed 响应,以及一个包含errorresult 的上下文。

【讨论】:

太棒了。这看起来正是我正在寻找的。我会尽快尝试并报告。非常感谢。 我遇到了一些麻烦。该代码适用于一个对象,但当我输入两行数据时不返回任何内容。我认为当我收到查询时,它返回 1 个对象,而不是按行拆分它们。例如,我收到一个关于 redgreen 的查询,而不是一个针对红色和一个针对绿色的查询。我是否使用了不正确的 html 字段?当我使用 <textfield> 查询 1 个对象时它有效,但当我添加新行时它为零。该代码似乎应该可以正常工作。 你能否为query添加一个print(query)语句(拆分后,所以在第二个if之前),并分享值是什么。 控制台没有打印任何内容。 Get请求正在通过,如下:"GET /results/?q=apple%0D%0Apink HTTP/1.1" 200 14350 @juju:啊,那是回车。我们.strip(..)所有元素是什么?

以上是关于如何使用Django.db.models Q模块查询多行用户输入文本数据的主要内容,如果未能解决你的问题,请参考以下文章

AttributeError:模块'django.db.models'没有属性'DataField'[关闭]

Django---进阶6

Django---进阶6

getattr - 异常值:模块 'django.db.models' 没有属性 'model_name''

Django篇之F,Q

Django搭建简易博客教程-Models