Как избежать выбора n + 1 в django? - PullRequest
9 голосов
/ 17 июня 2011

У меня очень простая модель данных с отношением один ко многим между видео и комментариями

class Video(models.Model):
    url = models.URLField(unique=True)
    .....

class Comment(models.Model):
    title = models.CharField(max_length=128)
    video = models.ForeignKey('Video')
        .....

Я хочу запросить видео и получить весь объектный граф (видео со всеми комментариями).Глядя на SQL, я вижу, что он делает два выбора, один для видео и один для комментариев.Как мне этого избежать?Я хочу сделать соединение и захватить все сразу.

Возможно ли это сделать с помощью django?

Ответы [ 3 ]

12 голосов
/ 17 июня 2011

Для ForeignKey вы можете использовать selected_related () :

Comment.objects.select_related('video').all()

Он будет генерировать только один запрос, собирая комментарии для вас, а также видео.

Для чего-то более сложного (такого как M2M) вам нужно внешнее приложение, такое как unjoinify , чтобы выполнить оптимизацию, но оно использует запросы SQL, чтобы затем поместить их обратно в объекты.

Если вас это не устраивает (у меня есть), у вас есть несколько альтернатив:

1 голос
/ 17 июня 2011

Что вам нужно сделать, это использовать select_related в комментарии.

Допустим, вам нужно найти все видео, заголовок которых начинается с 'The' и комментарии, связанные с ним

comments = Comment.objects.filter(video__title__starts_with='The')
           .select_related('video').all()

Это загрузит все комментарии и соответствующий объект Video для этого комментария.Вам по-прежнему нужно поворачиваться над видео, чтобы перебрать видео.Используйте функцию python itertools.groupby, чтобы сделать это в памяти.

0 голосов
/ 17 июня 2011

Посмотрите, если выбрать связанный работает так, как вы ожидаете, он был сделан только для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...