Невозможно заставить Django выполнять только один запрос с несколькими соединениями, используя методы .all()... или даже .raw(sql)
Я новичок в Django и хотел попробовать преобразовать уже существующее PHP приложение в Django.
Но я уже застрял на создании набора запросов для нескольких объединенных таблиц, чтобы выполнялся только один sql-запрос.
Я использую БД MySql.
Мне уже удалось создать представление, которое уменьшает количество запросов с .all(), .filter, .order_by и несколькими .select_related, но не смог заставить его сделать только один вызов sql-запроса.
Поэтому я подумал, что мне следует использовать метод .raw(sql), но даже такой подход заставил Django выполнять сотни одиночных sql-запросов без соблюдения джойнов.
Может быть, вы могли бы помочь мне немного заставить эту, обычно простую вещь, работать в Django?
Вот мой оригинальный SQL-запрос, который работает абсолютно нормально при запуске в MySql и дает хороший набор результатов:
SELECT
`hosts`.`id`,
`hosts`.`hostname`,
`domains`.`domain_name`,
`hosts`.`description`,
`hosts`.`installation_by_company_id`,
`hosts`.`care_by_company_id`,
`hosts`.`system_care_by_department_id`,
`hosts`.`system_care_accounting_type_id`,
`os`.`operatingsystem`,
`os`.`lsbdistcodename`,
`os`.`lsbdistrelease`,
`os`.`lsbmajdistrelease`,
`system_care_department`.`department_name` AS `system_care_department`,
`additional_software_care_department`.`department_name` AS `additional_software_care_department`,
`system_installation_company`.`company_name` AS `system_installation_company`,
`system_installation_company`.`company_abrebreation` AS `system_installation_company_abrebreation`
FROM
`hosts`
JOIN
`domains` ON `hosts`.`domain_id` = `domains`.`id`
JOIN
`hosts_fix_data_scans` ON `hosts_fix_data_scans`.`host_id` = `hosts`.`id`
JOIN
`os` ON `os`.`id` = `hosts_fix_data_scans`.`os_id`
JOIN
`companies_departments` ON `companies_departments`.`id` = `hosts`.`system_care_by_department_id`
JOIN
`companies_departments` AS `system_care_department` ON `system_care_department`.`id` = `hosts`.`system_care_by_department_id`
JOIN
`companies_departments` AS `additional_software_care_department` ON `additional_software_care_department`.`id` = `hosts`.`additional_software_care_by_department_id`
JOIN
`companies` AS `system_installation_company` ON `system_installation_company`.id = `hosts`.`installation_by_company_id`
WHERE
`hosts`.`offline` = 0
ORDER BY `system_care_department`;
Это был мой первый подход, который привел к множеству (столько, сколько записей в таблице hosts = 141) дополнительных запросов к таблице os и одному дополнительному запросу к таблице software_updates:
machines = SinfraHosts.objects.all().filter(offline=0).order_by('system_care_by_department').select_related('domain').select_related('last_fix_data_scan').select_related('installation_by_company').select_related('system_care_by_department').select_related('care_by_company')
OK, но как насчет использования моего SQL запроса напрямую с таким подходом:
machines = SinfraSqlHosts.objects.raw(sql)
Дела обстоят еще хуже: в то время как мой первый подход привел к 143 однократно выполненным sql-запросам, подход с использованием SQL-запроса напрямую через метод .raw(sql) привел к невероятным 284 однократно выполненным sql-запросам!
Может ли кто-нибудь помочь мне заставить вышеприведенный запрос выполняться как один единственный запрос в моем представлении и возвращать правильный набор результатов?
Заранее большое спасибо, ваш Анри
Можете ли вы поделиться кодом ваших моделей, чтобы люди могли понять, как создаются таблицы вашей базы данных и с какими отношениями.
Совет: Вам не нужно использовать all и filter в одном запросе, также для select_related(), вместо того, чтобы использовать его для нескольких колонок по одной, вы можете просто использовать его один раз и добавить имена колонок, разделенные запятой select_related('domain', 'last_fix_data_scan', 'installation_by_company')