Поместите Django ORM итерации в один запрос - PullRequest
0 голосов
/ 09 января 2019

У меня есть три модели:

class Box(models.Model):
    name = models.TextField(blank=True, null=True)


class Toy(models.Model):
    box = models.ForeignKey(Box, related_name='toys')


class ToyAttributes(models.Model):
    toy = models.ForeignKey(Toy)
    color = models.ForeignKey(Color, related_name='colors')

И список:

pairs = [[10, 3], [4, 5], [1, 2]]

Где каждое значение представляет собой пару или поле и идентификаторы цвета. Мне нужно отфильтровать эти данные и вернуть коробки с игрушками нужного цвета.

Теперь я делаю это:

for n in list:
    box = Box.objects.filter(id=n[0], toys__colors=n[1])
    if box.exist():
        ...

Но для длинных списков требуется много времени, как я понимаю, из-за множества SQL-запросов. Могу ли я сделать это быстрее? Можно ли получить только нужные ящики за один запрос и как я могу это сделать? Спасибо!

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Это должно работать для вас.

from django.db.models import Q

pairs = [[10, 3], [4, 5], [1, 2]]

conditions = [Q(id=box) & Q(toys__colors=color) for box, color in pairs]

query = Q()
for c in conditions:
    query |= c

Box.objects.filter(query)
0 голосов
/ 09 января 2019

Вы должны взглянуть на django Q function и построить свой запрос в цикле, добавляя значения в Q следующим образом:

query = Q()
for box_id, toy_color in [[10, 3], [4, 5], [1, 2]]:
   query |= Q(Q(id=box_id) & Q(toys__colors=toy_color))
Box.objects.filter(query)
...