动态构造Django过滤查询的args和kwargs

21 投票
3 回答
14910 浏览
提问于 2025-04-17 08:23

我正在动态构建一些Django的过滤查询,参考了这个例子

kwargs = { 'deleted_datetime__isnull': True }
args = ( Q( title__icontains = 'Foo' ) | Q( title__icontains = 'Bar' ) )
entries = Entry.objects.filter( *args, **kwargs )

我只是对如何构建args的内容不太确定。假设我有这个数组:

strings = ['Foo', 'Bar']

我该如何从这里得到:

args = ( Q( title__icontains = 'Foo' ) | Q( title__icontains = 'Bar' ) 

我能做到的最接近的是:

for s in strings:
    q_construct = Q( title__icontains = %s) % s
    args.append(s)

但我不知道怎么设置|这个条件。

3 个回答

1
firstQ = [
    Q(...),
    Q(...),
    Q(...)
]
import functools
functools.reduce(lambda a, b: a & b, Qrelationship)
firstQ = [
    Q(...),
    Q(...),
    Q(...)
]
secondQ = [
    Q(...),
    Q(...),
    Q(...)
]
import functools
combined = functools.reduce(lambda a, b: a | b, [
    functools.reduce(lambda a, b: a & b, firstQ),
    functools.reduce(lambda a, b: a & b, secondQ)
])
myqueryset = Model.objects.filter(combined)
# Make sure you apply the Q's first (BEFORE any other filter) or it will fail silently

在我的情况下,我需要把不同的过滤器组合在一起,也就是用“与”的方式来处理。

14

你有一个包含Q类对象的列表,

args_list = [Q1,Q2,Q3]   # Q1 = Q(title__icontains='Foo') or Q1 = Q(**{'title':'value'})  
args = Q()  #defining args as empty Q class object to handle empty args_list
for each_args in args_list :
    args = args | each_args

query_set= query_set.filter(*(args,) ) # will excute, query_set.filter(Q1 | Q2 | Q3)
# comma , in last after args is mandatory to pass as args here
13

你可以直接用一种叫做关键字参数的格式来遍历它(我不知道这个术语是否正确)

argument_list = [] #keep this blank, just decalring it for later
fields = ('title') #any fields in your model you'd like to search against
query_string = 'Foo Bar' #search terms, you'll probably populate this from some source

for query in query_string.split(' '):  #breaks query_string into 'Foo' and 'Bar'
    for field in fields:
        argument_list.append( Q(**{field+'__icontains':query_object} ) ) 

query = Entry.objects.filter( reduce(operator.or_, argument_list) )

# --UPDATE-- here's an args example for completeness

order = ['publish_date','title'] #create a list, possibly from GET or POST data
ordered_query = query.order_by(*orders()) # Yay, you're ordered now!

这段代码会在你的 query_string 中的每个字符串和 fields 中的每个字段进行查找,并把结果用“或”连接起来

我希望我还能找到我最初的来源,不过这段代码是我自己用的代码的改编版。

撰写回答