【问题标题】:Looking for Django any() and all() on querysets在查询集上寻找 Django any() 和 all()
【发布时间】:2012-04-19 16:23:59
【问题描述】:

我有一个包含 13 个复选框的表单,它们共同构成了我的搜索条件...除了我还添加了一对 ALL 或 ANY 的单选按钮。

我希望能摆脱一些优雅的事情,例如:

priority_ids = request.GET.getlist("priority")  # checkboxes
collection   = request.GET.get("collection")    # radio buttons
priorities = []
for priority_id in priority_ids:
    priorities.append(Q(focus__priority=priority_id))
if   (collection == "any"): qset = any(priorities)
elif (collection == "all"): qset = all(priorities)

但是,any() 和 all() 返回一个布尔值,而不是我可以在过滤器中使用的查询集。我想要一个与“Q(...) | Q(...) | Q(...)”或“Q(...) & Q(.. .) & Q(...)" 适用于 1 到 13 个标准。

【问题讨论】:

    标签: django combinations django-queryset


    【解决方案1】:

    Django 无需为此做任何事情。您只需将Q-s 与&| 组合起来,以简单的循环或更紧凑的方式与reduce 组合。

    关于术语,在我看来,您将Q 称为查询集,但事实并非如此。它是查询集上的过滤器。 像下面这样的东西应该可以工作:

    priority_ids = request.GET.getlist("priority")
    collection   = request.GET.get("collection")
    priority_filters = []
    for priority_id in priority_ids:
        priority_filters.append(Q(focus__priority=priority_id))
    
    base_qs = SomeModel.objects.all()
    
    if collection == "any":
       filtered_qset = base_qs.filter(reduce(operator.or_, priority_filters))
    elif collection == "all":
       filtered_qset = base_qs.filter(reduce(operator.and_, priority_filters))
    

    【讨论】:

    • 请注意,您的lambdas 可以分别替换为operator.or_operator.and_
    • 当我们这样做的时候,不妨试试priority_filters = [Q(focus__priority=p_id) for p_id in priority_ids] :)
    • 另外,any 的情况可能可以通过使用 __in 查找类型 (SomeModel.objects.filter(focus__priority__in=priority_ids)) 来处理。我认为您必须为all 这样做。
    【解决方案2】:

    您可以使用 Q() 进行动态查询,如下所示...

    from django.db.models import Q 
    from priority_app.models import Priority  # get your model identified
    
    
    #(whatever API place you had this):
    
        priority_id = request.GET.get("priority")   #getlist is isn't a proper list
        field_id = request.query_params.get('collection')
        if priority_id:
            priority_id_list = list(map(str.strip, priority_id.split(",")))
    
    
            dynamic_query_filters = Priority.objects.none()
            for a_item in priority_id_list:
                if collection == "any":
                    dynamic_query_filters |= (Q(id=a_item))    # OR query
                else:
                    dynamic_query_filters &= (Q(id=a_item))   # AND query
        
            queryset = Priority.objects.filter(dynamic_query_filters)   
            # you will notice, it executes in order of "query", maybe take them in different variables and chain them accordingly.
           
     
    

    【讨论】:

    • 这是对所提出的问题试图解决的方式的字面解决方案。
    猜你喜欢
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    相关资源
    最近更新 更多