Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
过滤具有可变参数数的多个Django模型字段_Django_Django Queryset_Django Q - Fatal编程技术网

过滤具有可变参数数的多个Django模型字段

过滤具有可变参数数的多个Django模型字段,django,django-queryset,django-q,Django,Django Queryset,Django Q,我正在实现搜索功能,可以通过匹配多个表和这些表中的多个字段来查找记录 假设我想根据客户的名字或姓氏,或者根据下单的ID查找客户,下单的ID存储在与客户不同的型号中。 我已经实现的简单场景是,用户只在搜索字段中键入单个单词,然后使用DjangoQ使用直接字段引用或related\u query\u name引用来查询Order模型,如: result = Order.objects.filter( Q(customer__first_name__icontains=user_inp

我正在实现搜索功能,可以通过匹配多个表和这些表中的多个字段来查找记录

假设我想根据客户的名字或姓氏,或者根据下单的ID查找客户,下单的ID存储在与客户不同的型号中。 我已经实现的简单场景是,用户只在搜索字段中键入单个单词,然后使用Django
Q
使用直接字段引用或
related\u query\u name
引用来查询
Order
模型,如:

result = Order.objects.filter(
        Q(customer__first_name__icontains=user_input)
        |Q(customer__last_name__icontains=user_input)
        |Q(order_id__icontains=user_input)
        ).distinct()
小菜一碟,一点问题也没有

但是,如果用户想要缩小搜索范围并在搜索字段中键入多个单词,该怎么办呢

示例:用户键入了
Bruce
,并通过搜索返回了大量记录

现在,他/她希望更具体一些,并在搜索中添加客户的姓氏。因此,搜索变成了
Bruce Wayne
,在将其拆分为我的
Bruce
Wayne
的单独部分之后。显然,我不想搜索
订单
模型,因为
order\u id
是一个单词实例,一次找到客户就足够了,所以在这种情况下,我将其从查询中删除

现在,我试图通过名字和姓氏匹配客户,我还想处理提供数据的顺序是随机的情况,以正确处理
Bruce Wayne
Wayne Bruce
,这意味着我仍然有客户全名,但名字和姓氏的位置不固定

这就是我要寻找答案的问题:如何构建一个查询来搜索模型的多个字段,而不知道哪个搜索词属于哪个表


我猜这个解决方案很简单,肯定有一种优雅的方法可以创建这样一个动态查询,但我想不出一种方法。您可以动态地或可变数量的Q对象组合在一起,以实现所需的搜索。下面的方法使得添加或删除要包含在搜索中的字段变得非常简单

from functools import reduce
from operator import or_


fields = (
    'customer__first_name__icontains',
    'customer__last_name__icontains',
    'order_id__icontains'
)
parts = []
terms = ["Bruce", "Wayne"]  # produce this from your search input field
for term in terms:
    for field in fields:
        parts.append(Q(**{field: term}))

query = reduce(or_, parts)

result = Order.objects.filter(query).distinct()

使用
reduce
将Q对象组合在一起。要归功于答案的这一部分。

您可以动态或可变数量的Q对象组合在一起,以实现所需的搜索。下面的方法使得添加或删除要包含在搜索中的字段变得非常简单

from functools import reduce
from operator import or_


fields = (
    'customer__first_name__icontains',
    'customer__last_name__icontains',
    'order_id__icontains'
)
parts = []
terms = ["Bruce", "Wayne"]  # produce this from your search input field
for term in terms:
    for field in fields:
        parts.append(Q(**{field: term}))

query = reduce(or_, parts)

result = Order.objects.filter(query).distinct()

使用
reduce
将Q对象组合在一起。要归功于答案的这一部分。

我提出的解决方案相当复杂,但它的工作方式正是我想要处理这个问题的方式:

search_keys = user_input.split()
if len(search_keys) > 1:
    first_name_set = set()
    last_name_set = set()
    for key in search_keys:
        first_name_set.add(Q(customer__first_name__icontains=key))
        last_name_set.add(Q(customer__last_name__icontains=key))
    query = reduce(and_, [reduce(or_, first_name_set), reduce(or_, last_name_set)])

else:
    search_fields = [
        Q(customer__first_name__icontains=user_input),
        Q(customer__last_name__icontains=user_input),
        Q(order_id__icontains=user_input),
    ]
    query = reduce(or_, search_fields)

result = Order.objects.filter(query).distinct()

我提出的解决方案相当复杂,但它的工作方式正是我想要处理这个问题的方式:

search_keys = user_input.split()
if len(search_keys) > 1:
    first_name_set = set()
    last_name_set = set()
    for key in search_keys:
        first_name_set.add(Q(customer__first_name__icontains=key))
        last_name_set.add(Q(customer__last_name__icontains=key))
    query = reduce(and_, [reduce(or_, first_name_set), reduce(or_, last_name_set)])

else:
    search_fields = [
        Q(customer__first_name__icontains=user_input),
        Q(customer__last_name__icontains=user_input),
        Q(order_id__icontains=user_input),
    ]
    query = reduce(or_, search_fields)

result = Order.objects.filter(query).distinct()

这回答了部分与动态生成查询相关的问题,但可能我没有把问题讲清楚,所以我更新了问题。这回答了部分与动态生成查询相关的问题,但可能我没有把问题讲清楚,所以我更新了问题。