Django objects.all () выполняет более 360 запросов — как я могу оптимизировать это множество?

#django

#django

Вопрос:

Новичок в Django, третий вопрос по нему сегодня…

У меня определены следующие (упрощенные) модели:

 class Band(models.Model):
    bandname = models.CharField('Band name', max_length=300)

class Release(models.Model):
    title = models.CharField(max_length=300)
    artist = models.ManyToManyField('Band')
    formats = models.ManyToManyField('Format')

class Format(models.Model):
    kind = models.CharField(max_length=300)

class Song(models.Model):
    title = models.CharField(max_length=500)
    release = models.ForeignKey('Release')
  

(Я удалил дополнительные поля для удобства чтения)

Теперь, когда я пытаюсь выполнить следующий запрос, он добавляет сотни дополнительных запросов на страницу:

 s = Song.objects.all() # adds 367 queries
  

Я пытался изменить его на это:

 s = Song.objects.select_related('band', 'release').all() # adds 245 queries
  

Это все еще отстой, и я не знаю, что еще я могу сделать. В моей базе данных 122 песни, 52 релиза, 39 групп. Не уверен, помогает ли это, но я в растерянности.

Есть какие-нибудь советы о том, как это оптимизировать? Мне нужно иметь возможность показывать группу и название релиза для каждого Song . Release Для Band многих много, потому что некоторые из них являются разделенными релизами нескольких исполнителей.

спасибо, Мэтт

Ответ №1:

Django select_related не следует отношениям «многие ко многим», и я предполагаю, что именно это является причиной большого количества запросов.

Я предлагаю использовать values() , и double__underscore__notation для получения требуемых значений. Что-то похожее на это должно работать на django 1.3 и выше:

 s = Song.objects.values('title', 'release__title', 'release__artist__bandname')
  

Комментарии:

1. Спасибо за это — почти работает. Я получаю: Invalid field name: 'release__artist__bandname' — Я могу подтвердить, что это правильные имена полей.

2. Ах да, это поле «многие могут». Хм, возможно, мне придется пересмотреть свое решение. Я думаю, что этот был не совсем удачным. На самом деле я никогда не использовал двойное подчеркивание в поле «многие ко многим». Это то, что мне нужно изучить.

3. У меня есть метод внутри, Release который возвращает разделенный запятыми список строк Artists , но, похоже, я тоже не могу его использовать … хм. Так близко!

4. Это все еще может не сработать, но я не был уверен, следует ли мне использовать ‘release__artist__bandname’ или ‘release___band__name’. В любом случае, в зависимости от количества имеющихся у вас диапазонов, ваш набор результатов будет очень большим.

5. просто ошибка release___band__name с «Не удается разрешить ключевое слово ‘release___band__name’ в поле. Варианты: имя файла, идентификатор, is_featured, релиз, заголовок «. Было бы разумнее запустить отдельный запрос для исполнителей (и / или релизов) и объединить их с песнями? Или, может быть, просто напишите какой-нибудь чистый SQL…