Как выбрать из нескольких таблиц в одном запросе с Django? - PullRequest
10 голосов
/ 11 марта 2010

У меня есть две таблицы, одна «Компания» и одна «Сотрудник»:

class Company(models.Model):
    name = models.CharField(max_length=60)

class Employee(models.Model):
    name = models.CharField(max_length=60)
    company = models.ForeignField(Company)

И я хочу перечислить каждого сотрудника в таблице, рядом с которой находится Компания. Что достаточно просто, вызвав employees = Employee.objects.all() и в цикле шаблона через него и вызвав {{employee.company.name}}.

Проблема с этими решениями состоит в том, что будет создан новый запрос для каждого элемента в цикле. Таким образом, для каждого сотрудника будет один запрос к компании, который выглядит примерно так:

SELECT `company`.`id`, `company`.`name`
FROM `company`
WHERE `company`.`id` = 1 # This will of course be the employee.company_id

Вместо этого я хочу сделать это соединение изначально в том же запросе, получая сотрудников. Примерно так:

SELECT `employee`.`name` AS `name`,
       `company`.`name` AS `company_name`
FROM `employee` INNER JOIN `company` ON `employee`.`company_id` = `company`.`id`

Возможно ли это с помощью Django QuerySet? Если нет, есть ли способ я могу обойти это, чтобы решить эту проблему (без raw SQL)? Или это поведение следует игнорировать, кэшировать и считать «оптимизированным»?

Ответы [ 3 ]

22 голосов
/ 11 марта 2010

Использование select_related () предварительно заполнит соответствующие атрибуты:

Employee.objects.select_related()
7 голосов
/ 11 марта 2010

Полагаю, вы ищете метод select_related вашего набора запросов. См документ

select_related ()

Возвращает QuerySet, который будет автоматически «следить» за внешним ключом отношения, выбирая что дополнительные данные связанного объекта, когда это выполняет свой запрос. Это повышение производительности, которое приводит к (иногда намного) большие запросы, но означает дальнейшее использование внешнего ключа отношения не требуют базы данных запросы

6 голосов
/ 19 января 2018

Это старый вопрос, позвольте мне дать новый ответ.

На самом деле, вы можете сделать это:

employees = Employee.objects.all().values('id','name','company__name')

тогда Django автоматически найдет класс компании и найдет название компании для вас.

на странице шаблона, используйте {{employee.company__name}}, тогда она будет правильно отображать название компании.

...