Ответ
Когда Django ORM недостаточно для сложных запросов (оконные функции, рекурсивные CTE, специфичные JOIN), используются сырые SQL-запросы или расширения ORM.
Способы работы с сырым SQL в Django:
-
Manager.raw(): Выполнение SELECT-запросов с маппингом результатов в модели.from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) # Сырой запрос с параметрами для безопасности people = Person.objects.raw(''' SELECT id, first_name, last_name FROM myapp_person WHERE last_name = %s ORDER BY first_name DESC ''', [requested_last_name]) -
Прямое подключение к БД (
django.db.connection): Для запросов, не возвращающих модели (UPDATE, вызов функций).from django.db import connection def my_custom_sql(self): with connection.cursor() as cursor: cursor.execute(""" SELECT COUNT(*) AS url_count FROM myapp_url WHERE path LIKE %s """, ['/api/%']) row = cursor.fetchone() return row[0] -
Выражения
RawSQL: Встраивание SQL-фрагментов прямо в QuerySet.from django.db.models.expressions import RawSQL queryset = Person.objects.annotate( custom_field=RawSQL("some_column - %s", (param,)) )
Почему осторожно?
- SQL-инъекции: Всегда используйте параметризованные запросы (
%s), а не конкатенацию строк. - Переносимость: Сырой SQL привязывает код к конкретной СУБД (PostgreSQL, MySQL).
- Поддержка: Усложняет миграции и может обойти валидацию ORM.
Лучшая практика: Сначала изучите возможности ORM (F(), Q(), Window, Subquery). К сырому SQL прибегайте только в случае необходимости.