Django автоматически транслирует методы QuerySet в соответствующие SQL-выражения, которые затем выполняются в базе данных. Однако фреймворк также позволяет непосредственно определить SQL-запрос и выполнять его. Для этого применяется метод raw(), в который передается SQL-запрос:
from .models import Person
people = Person.objects.raw("SELECT id, name FROM hello_person")
# перебираем полученные строки
for person in people:
print(person.name)
# получаем один объект
print(people[0].name)
В данном случае в raw() передается запрос, который получает значения полей id и name из таблицы hello_person. Этот метод возвращает объект django.db.models.query.RawQuerySet, который, подобно QuerySet, также можно перебрать в цикле и извлечь из него данные.
Стоит учитывать, что данный метод должен возвращать набор строк. Также стоит отметить, что метод не учитывает никакие выражения фильтрации, которые идут до его вызова
# здесь filter НЕ окажет никакого влияния
people = Person.objects.filter(age__lt=35).raw("SELECT * FROM hello_person")
С помощью параметра params в метод raw() можно передать значения для параметров в SQL-запросе:
# определяем значение для параметра name
name_for_filter = "Tom"
# определяем значение для параметра age
age_for_filter = 35
people = Person.objects.raw("SELECT * FROM hello_person WHERE name = %s OR age > %s",
[name_for_filter, age_for_filter])
В данном случае SQL-запрос использует два параметра, которые определяются через спецсимволы %s. Второй параметр метода raw представляет
список аргументов, которые передаются в запрос вместо символов %s. Аргументы передаются по позиции, то есть значение name_for_filter передается на место первого
вхождения %s, второе значение - age_for_filter - на место второго вхождения %s и т.д.
Слабым местом метода raw() является то, что он позволяет выполнять только команду SELECT, которая возвращает набор строк. Если же мы хотим выполнить другие sql-команды:
UPDATE, INSERT или DELETE или другие типы SELECT-запросов, то в этом случае мы можем воспользоваться функционалом
django.db.connection.
Объект django.db.connection представляет подключение к базе данных:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("UPDATE hello_person SET name ='Tomas' WHERE name='Tom' AND age=22")
cursor.execute("SELECT * FROM hello_person WHERE name = 'Tomas'")
row = cursor.fetchone() # получаем одну строку
print(row)
Для использования подключения вначале необходимо получить курсор с помощью
метода connection.cursor(). А затем у курсора вызывается метод cursor.execute(), в который передается выполняемый sql-запрос.
Для возвращения результата применяются методы cursor.fetchone() и cursor.fetchall().
Также можно использовать параметры:
from django.db import connection
old_name = "Tomas"
new_name = "Tom"
with connection.cursor() as cursor:
cursor.execute("UPDATE hello_person SET name =%s WHERE name=%s", [new_name, old_name])
cursor.execute("SELECT * FROM hello_person WHERE name = 'Tom'")
rows = cursor.fetchall() # получаем все строки
for row in rows:
print(row)