简体   繁体   English

Django 在两个不同的多对多字段之间进行过滤

[英]Django Filter on between two different ManytoMany fields

I want to model a Cake with multiple Icings .我想model一个带有多个糖衣的蛋糕
Each Icings has a flavor.每个糖衣都有一种味道。
An Icing can belong to multiple Cakes so this needs to be a many-to-many relationship.一个结冰可以属于多个蛋糕,所以这需要是多对多的关系。

I achieved the requirement thourgh this model:我通过这个 model 达到了要求:

class Cake(models.Model):
     layers = models.ManyToManyField(Icing, through='CakeLayer')

class Icing(models.Model):
     flavour = models.CharField(max_length=200)

class CakeLayer(models.Model):
     cake = models.ForeignKey(Cake, on_delete=models.CASCADE)
     icing = models.ForeignKey(Icing, on_delete=models.CASCADE)
     order = models.IntegerField()

However, I want to query a cake which has a chocolate icing ontop of a vanila icing (ie chocolate_icing.order > vanila_icing.order )但是,我想查询一个在香草糖衣之上有巧克力糖衣的蛋糕(即chocolate_icing.order > vanila_icing.order

I cannot achieve it through Django's ORM but its rather simple by SQL.我无法通过 Django 的 ORM 实现它,但 SQL 相当简单。

SELECT * FROM "cake" 
    INNER JOIN "cakelayer" i1 
        ON ("cake"."id" = "cakelayer"."cake_id") 
    INNER JOIN "cakelayer" i2 
        ON ("cake"."id" = "cakelayer"."cake_id") 
    WHERE (i1.order > i2.order 
        AND i1.icing.flavor="chocolate"
        AND i2.icing.flavor="vanila"
        )

I would rather write python code than inject SQL.我宁愿写 python 代码也不愿注入 SQL。 Any idea how to convert this SQL to Django ORM syntax?知道如何将此 SQL 转换为 Django ORM 语法吗?

You can query for this with:您可以通过以下方式查询:

Cake.objects.filter(
    layers__flavour='vanilla'
).annotate(
    vorder=F('cakelayer__order')
).filter(
    layers__flavour='chocolate',
    cakelayer__order__gt=F('order')
)

Here we use .annotate(..) to obtain a reference to the layer that matches with vanilla, and then we can use that in the second join.这里我们使用.annotate(..)来获取与 vanilla 匹配的层的引用,然后我们可以在第二个连接中使用它。

This will construct a query that looks like:这将构造一个如下所示的查询:

SELECT cake.id, cakelayer.order AS vorder
FROM cake
INNER JOIN cakelayer ON cake.id = cakelayer.cake_id
INNER JOIN icing ON cakelayer.icing_id = icing.id
INNER JOIN cakelayer T4 ON cake.id = T4.cake_id
INNER JOIN icing T5 ON T4.icing_id = T5.id
WHERE icing.flavour = vanilla
  AND T4.order > cakelayer.order
  AND T5.flavour = chocolate

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM