【问题标题】:django dynamically filtering with q objectsdjango用q个对象动态过滤
【发布时间】:2012-10-16 02:56:40
【问题描述】:

我正在尝试根据用户输入标签查询数据库。标签的数量可以是0-5,所以我需要动态创建查询。

所以我有一个标签列表,tag_list,我要查询数据库:

design_list = Design.objects.filter(Q(tags__tag__contains = "tag1") and Q(tags__tag__contains = "tag2") and etc. etc. )

如何创建此功能?

【问题讨论】:

    标签: django django-models django-q


    【解决方案1】:

    您需要遍历 tag_list 并为每个应用一个过滤器。

    tag_list = ['tag1', 'tag2', 'tag3']
    base_qs = Design.objects.all()
    for t in tag_list:
        base_qs = base_qs.filter(tags__tag__contains=t)
    

    这将为您提供匹配 all 标记的结果,如您的示例所示 and。如果实际上您需要or,那么您可能需要 Q 对象。

    编辑:我想我现在有你要找的东西。

    tags = ['tag1', 'tag2', 'tag3']
    q_objects = Q() # Create an empty Q object to start with
    for t in tags:
        q_objects |= Q(tags__tag__contains=t) # 'or' the Q objects together
    
    designs = Design.objects.filter(q_objects)
    

    我对此进行了测试,它似乎工作得很好。

    编辑 2:感谢 Freenode 上 #django 中的 kezabelle 最初的想法。

    【讨论】:

    • 谢谢,这是有道理的。我已经尝试使用 Q 对象,但它没有返回正确的项目。我在这里做错了什么:`design_list = Design.objects.all() for t in tag_list: design_list = design_list.filter(Q(tags__tag__contains = t))`。它在只有一个标签但没有更多标签时有效。
    • 在您的代码中,Q 对象没有做任何事情。您很简单地创建了一个查询集,最终看起来像 Design.objects.filter(tags__tag__contains='tag1').filter(tags__tag__contains='tag2') 等。您可能想要的是 Design.objects.filter(Q(tags__tag__contains='tag1') | Q(tags__tag__contains='tag2')),但在某种程度上为您提供了可变数量的 Q 对象。
    • 好的,这就是我需要寻找的。​​span>
    • 如果你希望tags为空时designs为空,你可以使用Q(pk__in=[])作为q_objects的起始值。
    【解决方案2】:

    然后先准备一个标签列表,这样查询:

    tags = ['tag1', 'tag2',...]
    design_list = Design.objects.filter(tags__tag__contains__in = tags)
    

    【讨论】:

      【解决方案3】:

      你可以这样使用:

      my_dict = {'field_1': 1, 'field_2': 2, 'field_3': 3, ...}  # Your dict with fields
      or_condition = Q()
      for key, value in my_dict.items():
          or_condition.add(Q(**{key: value}), Q.OR)
      
      query_set = MyModel.objects.filter(or_condition)
      

      通过这种方式,您可以使用动态生成的字段名称。 您也可以将Q.AND 用于AND 条件。

      【讨论】:

      • 有没有办法用__in 做到这一点?想获得一个将字段与值列表匹配的 Q,其中字段名称和值列表由变量而不是文字给出?
      • @MichaelHoffmann 我不太明白你的意思,可能是这个:Q(**{"{}__in".format(key): value})
      【解决方案4】:

      您可能需要添加 AND 和 OR 条件

          query = (Q(fild1='ENABLE'))
          # Filter by list
          query.add(Q(fild2__in=[p.code for p in Objects.field.all()]), Q.AND)
      
          # filter OR
          q_objects = Q(field3='9999999')
          for x in myList:
              q_objects.add(Q(field3=x.code), Q.OR)
      
          query.add(q_objects, Q.AND)
      

      【讨论】:

        【解决方案5】:

        使用减少:

        from functools import reduce
        design_list = Design.objects.filter(reduce(lambda q1,q2: q1 & q2,
                                                   [Q(tags__tag__contains=t)
                                                    for t in tag_list]))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-08-23
          • 2018-12-19
          • 2021-09-18
          • 2014-04-11
          • 2010-12-29
          • 2011-01-13
          • 2018-03-23
          • 2012-09-09
          相关资源
          最近更新 更多