Невозможно заставить 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')

Вернуться на верх