如何在 Django 中动态组合 OR 查询过滤器?

2025-02-27 09:05:00
admin
原创
82
摘要:问题描述:从示例中您可以看到多个 OR 查询过滤器:Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3)) 例如,结果为:[<Article: Hello>, <Article: Goodbye>, <Article: Hello ...

问题描述:

从示例中您可以看到多个 OR 查询过滤器:

Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))

例如,结果为:

[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]

但是,我想从列表中创建此查询过滤器。该怎么做?

例如[1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))


解决方案 1:

您可以按如下方式链接您的查询:

values = [1,2,3]

# Turn list of values into list of Q objects
queries = [Q(pk=value) for value in values]

# Take one Q object from the list
query = queries.pop()

# Or the Q object with the ones remaining in the list
for item in queries:
    query |= item

# Query the model
Article.objects.filter(query)

解决方案 2:

要构建更复杂的查询,还可以选择使用内置 Q() 对象的常量 Q.OR 和 Q.AND 与 add() 方法,如下所示:

list = [1, 2, 3]
# it gets a bit more complicated if we want to dynamically build
# OR queries with dynamic/unknown db field keys, let's say with a list
# of db fields that can change like the following
# list_with_strings = ['dbfield1', 'dbfield2', 'dbfield3']

# init our q objects variable to use .add() on it
q_objects = Q(id__in=[])

# loop trough the list and create an OR condition for each item
for item in list:
    q_objects.add(Q(pk=item), Q.OR)
    # for our list_with_strings we can do the following
    # q_objects.add(Q(**{item: 1}), Q.OR)

queryset = Article.objects.filter(q_objects)

# sometimes the following is helpful for debugging (returns the SQL statement)
# print queryset.query

解决方案 3:

使用python 的 reduce 函数来编写 Dave Webb 答案的更简短的方法:

# For Python 3 only
from functools import reduce

values = [1,2,3]

# Turn list of values into one big Q objects  
query = reduce(lambda q,value: q|Q(pk=value), values, Q())  

# Query the model  
Article.objects.filter(query)  

解决方案 4:

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

values = [1, 2, 3]
query = reduce(or_, (Q(pk=x) for x in values))

解决方案 5:

也许使用 sql IN 语句更好。

Article.objects.filter(id__in=[1, 2, 3])

请参阅queryset api 参考。

如果您确实需要使用动态逻辑进行查询,您可以执行以下操作(丑陋+未经测试):

query = Q(field=1)
for cond in (2, 3):
    query = query | Q(field=cond)
Article.objects.filter(query)

解决方案 6:

解决方案使用reduceor_运算符按乘法字段进行过滤。

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

filters = {'field1': [1, 2], 'field2': ['value', 'other_value']}

qs = Article.objects.filter(
   reduce(or_, (Q(**{f'{k}__in': v}) for k, v in filters.items()))
)

psf是一个新的格式字符串文字。它是在 Python 3.6 中引入的

解决方案 7:

查看文档:

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}

请注意,此方法仅适用于主键查找,但这似乎正是您想要做的。

所以你想要的是:

Article.objects.in_bulk([1, 2, 3])

解决方案 8:

如果我们想以编程方式设置我们想要查询的数据库字段:

import operator
questions = [('question__contains', 'test'), ('question__gt', 23 )]
q_list = [Q(x) for x in questions]
Poll.objects.filter(reduce(operator.or_, q_list))

解决方案 9:

For 循环

values = [1, 2, 3]
q = Q(pk__in=[]) # generic "always false" value
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)

减少

from functools import reduce
from operator import or_

values = [1, 2, 3]
q_objects = [Q(pk=val) for val in values]
q = reduce(or_, q_objects, Q(pk__in=[]))
Article.objects.filter(q)

这两个都相当于Article.objects.filter(pk__in=values)

为什么Q()危险

values当为空时,考虑你想要什么很重要。许多以Q()作为起始值的答案将返回所有内容Q(pk__in=[])是一个更好的起始值。它是一个始终失败的 Q 对象,优化器可以很好地处理它(即使对于复杂的方程式也是如此)。

Article.objects.filter(Q(pk__in=[]))  # doesn't hit DB
Article.objects.filter(Q(pk=None))    # hits DB and returns nothing
Article.objects.none()                # doesn't hit DB
Article.objects.filter(Q())           # returns everything

如果在为空时返回所有内容values,则应使用 AND 来~Q(pk__in=[])确保行为:

values = []
q = Q()
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # only Tolkien

q &= ~Q(pk__in=[])
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # everything

Q()什么也不是,不是一个总是成功的 Q 对象。任何涉及它的操作都会将其完全丢弃。

解决方案 10:

您可以使用 |= 运算符以编程方式使用 Q 对象更新查询。

解决方案 11:

这是动态pk列表:

pk_list = qs.values_list('pk', flat=True)  # i.e [] or [1, 2, 3]

if len(pk_list) == 0:
    Article.objects.none()

else:
    q = None
    for pk in pk_list:
        if q is None:
            q = Q(pk=pk)
        else:
            q = q | Q(pk=pk)

    Article.objects.filter(q)

解决方案 12:

另一个选项我直到最近才意识到——QuerySet也覆盖了&|~等运算符。 OR Q 对象的其他答案是这个问题的更好解决方案,但出于兴趣/争论的考虑,你可以这样做:

id_list = [1, 2, 3]
q = Article.objects.filter(pk=id_list[0])
for i in id_list[1:]:
    q |= Article.objects.filter(pk=i)

str(q.query)将返回一个包含子句中所有过滤器的查询WHERE

解决方案 13:

找到动态字段名称的解决方案

def search_by_fields(value, queryset, search_in_fields):
    if value:
        value = value.strip()

    if value:
        query = Q()
        for one_field in search_in_fields:
            query |= Q(("{}__icontains".format(one_field), value))

        queryset = queryset.filter(query)

    return queryset

解决方案 14:

简单..

从 django.db.models 导入 Q 导入你的模型 args = (Q(visibility=1)|(Q(visibility=0)&Q(user=self.user))) #Tuple 参数={} #dic order = 'create_at' limit = 10

Models.objects.filter(*args,**parameters).order_by(order)[:limit]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3911  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2721  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   61  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   61  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   54  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用