【问题标题】:django how to dynamically create nested and or queriesdjango如何动态创建嵌套和或查询
【发布时间】:2020-02-20 20:07:40
【问题描述】:

我有两种类型的过滤器列表,如下所示

a_filter = ['a', 'b', 'c']
b_filter = ['x', 'y', 'z']

我必须结合 in 查询 a_filter 和布尔字段查询 b_filter 如下所示

Item.objects.filter(a__in=a_filter, x=True, y=True, z=True)

如何动态创建此查询?我到了下面

filters = {
  a_filter__in:a_filter,
}

and_condition = Q(**filters)

if len(b_filter) > 0:
  or_cond = Q()
  for filter in b_filter:
    or_cond.add(Q(**{filter:True}), Q.AND)

and_condition.add(or_filter)

Item.objects.filter(and_condition)

这会在两个过滤器查询之间创建额外的(OR: (AND: ),如下所示

(AND: 'a_filter__in': ['a', 'b', 'c'), (OR: (AND: ), (AND:('x':True, 'y':True, 'z':True))

如何编写一个正确工作的查询?

【问题讨论】:

    标签: django


    【解决方案1】:

    您不需要Q 对象来获取您引用的特定查询。

    这就够了:

    bool_kwargs = {k: True for k in b_filter}
    Item.objects.filter(a__in=a_filter, **bool_kwargs)
    

    另外,你给出的例子也行不通。假设您的想法如下:

    filters = {
        "a__in": a_filter,
    }
    
    and_condition = Q(**filters)
    
    if len(b_filter) > 0:
        or_cond = Q()
        for filter in b_filter:
            or_cond.add(Q(**{filter: True}), Q.AND)
    
        and_condition.add(or_cond)
    
    Item.objects.filter(and_condition)
    

    如果您仍然想使用Q 对象或者Q.AND 应该是Q.OR(正如or_cond 变量名所暗示的那样),您可以这样做:

    from functools import reduce
    from operator import or_ # replace or_ with and_ for Q.AND
    
    bool_q_list = [Q(k=True) for k in b_filter]
    bool_q = reduce(or_, bool_q_list) # replace or_ with and_ for Q.AND
    Item.objects.filter(bool_q, a__in=a_filter)
    

    【讨论】:

      猜你喜欢
      • 2016-04-02
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      相关资源
      最近更新 更多