Django select_related по цепочкам внешних ключей - PullRequest
0 голосов
/ 19 сентября 2018

Я прочитал документацию и все связанные с этим вопросы здесь, но я не совсем понял, как select_related ведет себя с цепочкой / несколькими внешними ключами.

Предположим, у нас есть следующие модели:

class RecordLabel(models.Model):
   title = models.CharField(...)

class Band(models.Model):
   band_name = models.CharField(...)

class Artist(models.Model):
   record_label = models.ForeignKey(RecordLabel,...)
   belongs_to_band = models.ForeignKey(Band, ...)

class Producer(models.Model):
   customer = models.ForeignKey(Artist, ...)

A. Как мы будем использовать select_related в запросе

Producer.objects.filter(...).select_related(?)

, чтобы всепредварительно загружен?Будет ли это выглядеть так:

Producer.objects.filter(...).select_related(
    'customer__record_label', 'customer__belongs_to_band')

и почему?

B. Если у класса Band есть «Жанр» в качестве внешнего ключа,

 class Genre(models.Model):
       genre_name = models.CharField(...)        

 class Band(models.Model):
       band_name = models.CharField(...)
       music_genre = models.ForeignKey(Genres, ...)

тогда, чтобы все было предварительно загружено, мы бы сделали что-то вроде этого:

Producer.objects.filter(...).select_related(
    'customer__record_label__music_genre', 'customer__record_label__band_name',
    'customer__belongs_to_band__music_genre', 'customer__belongs_to_band__music_genre') 

или что-то вроде этого:

Producer.objects.filter(...).select_related(
    'customer__record_label__music_genre', 'customer__record_label__band_name',
    'customer__belongs_to_band', 'customer__belongs_to_band') 

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Что касается вопроса B:

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

Примечание: IЗдесь снова отобразите окончательную версию ваших моделей, потому что в противном случае я запутался.

class RecordLabel(models.Model):
    title = models.CharField(...)

class Genre(models.Model):
    genre_name = models.CharField(...)

class Band(models.Model):
    band_name = models.CharField(...)
    music_genre = models.ForeignKey(Genre, ...)

class Artist(models.Model):
    record_label = models.ForeignKey(RecordLabel, ...)
    belongs_to_band = models.ForeignKey(Band, ...)

class Producer(models.Model):
    customer = models.ForeignKey(Artist, ...)

Чтобы выбрать все связанные модели (выполните один большой SQL-запрос на объединение):

qs = Producer.objects.filter(...).select_related(
    'customer__record_label',
    'customer__belongs_to_band__music_genre')

Первыйpart (customer) предварительно выбирает связанного исполнителя и соответствующий лейбл записи (__record_label);вторая часть не нуждается в поиске артиста, потому что он уже есть, но он продолжает предварительную выборку соответствующей группы (__belongs_to_band), а затем и связанный жанр (__music_genre).Теперь у вас есть SQL-запрос, который обращается ко всем 5 таблицам (моделям).

Подсказка: вы можете использовать qs.query, чтобы увидеть основную идею оператора SQL, сгенерированного вашим запросом;это должно дать вам представление о соединениях, которые он создает.

Если у вас возникли проблемы с запросом, вам следует добавить дополнительную информацию о том, что именно происходит и чего вы ожидаете.

0 голосов
/ 19 сентября 2018

Для вопроса А: передать аргументы в виде строк

qs = Producer.objects.filter(...).select_related(
    'customer__record_label', 'customer__belongs_to_band')

РЕДАКТИРОВАТЬ: кажется, что пропущенные кавычки были просто опечатка спрашивающего, а не реальный вопрос.

...