Django Фильтр между двумя различными полями ManytoMany. - PullRequest
1 голос
/ 02 мая 2020

Я хочу смоделировать торт с несколькими обледенением . Каждая глазурь имеет вкус. Обледенение может принадлежать нескольким пирогам, поэтому это должно быть отношение многих ко многим.

Я выполнил требование для этой модели:

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()

Однако Я хочу запросить торт с шоколадной глазурью поверх ванильной глазури (например, chocolate_icing.order > vanila_icing.order)

Я не могу добиться этого с помощью 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"
        )

Я бы лучше написал python код, чем внедрил SQL. Любая идея, как преобразовать этот SQL в Django ORM синтаксис?

1 Ответ

0 голосов
/ 02 мая 2020

Вы можете запросить это с помощью:

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

Здесь мы используем .annotate(..), чтобы получить ссылку на слой, который соответствует ванили, а затем мы можем использовать это во втором соединении.

Это создаст запрос, который выглядит следующим образом:

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 <b>T4.order > cakelayer.order</b>
  AND T5.flavour = chocolate
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...