I want to model a Cake with multiple Icings .
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:
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
)
I cannot achieve it through Django's ORM but its rather simple by 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. Any idea how to convert this SQL to Django ORM syntax?
You can query for this with:
Cake.objects.filter(
layers__flavour='vanilla'
).annotate(
).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.
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
AND T5.flavour = chocolate
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.