Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье объясняется, как выполнять необработанные sql-запросы к SQL Server из приложений Django. Необработанный SQL подходит для операций, не предоставляемых через Django ORM, например сложные Transact-SQL (T-SQL), пространственные запросы или критически важные для производительности операции.
Используйте connection.cursor()
Доступ к курсору базы данных непосредственно через объект Django connection :
from django.db import connection
def get_server_version():
with connection.cursor() as cursor:
cursor.execute("SELECT @@VERSION;")
row = cursor.fetchone()
return row[0]
Инструкция with гарантирует правильное закрытие курсора после использования.
Параметризованные запросы
Всегда используйте параметризованные запросы, чтобы предотвратить внедрение SQL. Передайте параметры в виде списка:
Note
В следующих примерах используется соглашение <app_label>_<model_name> об именовании таблиц по умолчанию Django (например, myapp_product). При переопределении db_table в модели Metaзамените это имя. Вы также можете прочитать имя после разрешения во время выполнения программы с помощью Product._meta.db_table.
from django.db import connection
def get_products_by_price(min_price, max_price):
with connection.cursor() as cursor:
cursor.execute(
"SELECT id, name, price FROM myapp_product WHERE price BETWEEN %s AND %s;",
[min_price, max_price],
)
results = cursor.fetchall()
return results
Important
Никогда не используйте форматирование строк или f-строки для подстановки значений в SQL-запросы. Всегда используйте параметризованные запросы (%s заполнители со списком параметров), чтобы предотвратить внедрение SQL.
Получение результатов
Курсор Django предоставляет несколько методов получения результатов:
from django.db import connection
def demonstrate_fetch_methods():
with connection.cursor() as cursor:
cursor.execute("SELECT id, name FROM myapp_product;")
# Fetch one row
row = cursor.fetchone()
# Fetch the next 10 rows (continues from where fetchone stopped)
rows = cursor.fetchmany(10)
# Fetch all remaining rows (continues from where fetchmany stopped)
all_rows = cursor.fetchall()
Возвращать результаты в виде словарей
Преобразуйте строки в словари с помощью cursor.description:
from django.db import connection
def dictfetchall(cursor):
columns = [col[0] for col in cursor.description]
return [dict(zip(columns, row)) for row in cursor.fetchall()]
def get_all_products():
with connection.cursor() as cursor:
cursor.execute("SELECT id, name, price FROM myapp_product;")
return dictfetchall(cursor)
Использование Manager.raw() для запросов модели
Если требуется необработанный SQL, но по-прежнему требуется экземпляры модели Django, используйте Manager.raw():
from myapp.models import Product
products = Product.objects.raw(
"SELECT id, name, price FROM myapp_product WHERE price > %s",
[10.00],
)
for product in products:
print(f"{product.name}: ${product.price}")
Запрос должен возвращать все поля, определенные в первичном ключе модели. Дополнительные поля загружаются лениво.
Выполнение инструкций DDL
Используйте необработанный SQL для операций схемы, которые Django не поддерживает напрямую:
from django.db import connection
def create_index():
with connection.cursor() as cursor:
cursor.execute(
"CREATE INDEX IX_product_name ON myapp_product (name) "
"INCLUDE (price);"
)
Несколько подключений к базе данных
Если вы используете несколько баз данных, укажите, какое подключение следует использовать:
from django.db import connections
def query_reporting_db():
with connections["reporting"].cursor() as cursor:
cursor.execute("SELECT COUNT(*) FROM myapp_product;")
return cursor.fetchone()[0]