代码之家  ›  专栏  ›  技术社区  ›  Dalvtor

Django ORM公司。用AND子句筛选多对多

  •  1
  • Dalvtor  · 技术社区  · 6 年前

    以下型号:

    class Item(models.Model):
        name = models.CharField(max_length=255)
        attributes = models.ManyToManyField(ItemAttribute)
    
    
    class ItemAttribute(models.Model):
        attribute = models.CharField(max_length=255)
        string_value = models.CharField(max_length=255)
        int_value = models.IntegerField()
    

    我也有一个 Item 它有两个属性, 'color': 'red' 'size': 3 .

    如果我有任何疑问:

    Item.objects.filter(attributes__string_value='red')
    Item.objects.filter(attributes__int_value=3)
    

    我会得到 项目 返回,按我的预期工作。

    但是,如果我尝试执行多个查询,例如:

    Item.objects.filter(attributes__string_value='red', attributes__int_value=3)
    

    我只想做一个和。这也不管用:

    Item.objects.filter(Q(attributes__string_value='red') & Q(attributes__int_value=3))
    

    输出为:

    <QuerySet []>
    

    为什么?我怎样才能建立这样一个查询 项目 返回,因为它具有 red 以及属性 3 ?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Chayemor    6 年前

    如果有任何用途,可以在Django中链接筛选器表达式:

    query = Item.objects.filter(attributes__string_value='red').filter(attributes__int_value=3')
    

    来自 DOCS :

    这将获取数据库中所有条目的初始查询集,添加一个筛选器,然后添加一个排除,然后添加另一个筛选器。最后的结果是一个包含所有条目的查询集,标题从2005年1月30日到今天发布。

    做这件事 .filter() 但对于动态参数:

    args = {
        '{0}__{1}'.format('attributes', 'string_value'): 'red',
        '{0}__{1}'.format('attributes', 'int_value'): 3
    }
    
    Product.objects.filter(**args)
    

    你可以 (如果你需要混合 AND OR )使用Django的 Q objects .

    关键字参数查询_“in filter()等。_”和__一起使用。如果需要执行更复杂的查询(例如,带有或语句的查询),可以使用q对象。

    q对象(django.db.models.q)是用于封装 关键字参数集合。指定了这些关键字参数 如上文__field lookups_157;所述。

    你应该有这样的东西而不是所有的 Q objects 在该过滤器中:

    ** import Q from django
    from *models import Item
    
    #assuming your arguments are kwargs
    final_q_expression = Q(kwargs[1])
    for arg in kwargs[2:..]
        final_q_expression = final_q_expression & Q(arg);
    result = Item.objects.filter(final_q_expression)
    

    这是我没有运行的代码,它在我的头上。如果愿意,就把它当作伪代码。

    不过,这并不能解释为什么你尝试的方法不太管用。也许这和 跨越关系的查找 以及要连接以获取这些值的表。我建议打印 yourQuerySet.query 可视化 raw SQL 这正在形成,这可能有助于指导你为什么 .filter( Q() & Q()) 不工作。