هرچند که ORM بهخوبی نیازهای عمومی ما را در جنگو برآورد میکند، اما گاهی اوقات برای کوئریهای پیچیده یا بهینهسازیهای خاص، استفاده از کوئریهای خام SQL بهترین راهحل است.
در کد زیر، یک کوئری سادهی خام برای دریافت محصولات با قیمت بالاتر از 100 را میبینید:
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM myapp_product WHERE price > %s", [100])
results = cursor.fetchall()
for row in results:
print(row)
این کار برای ما کنترل بیشتر بر کوئریها، امکان استفاده از ویژگیهای خاص دیتابیس و بهبود عملکرد در شرایط خاص را امکان پذیر میکند.
فقط دقت کنید که حتما از پارامترها (
%s
) بهجای ترکیب مستقیم مقادیر در کوئری استفاده کنید تا از حملات SQL Injection جلوگیری شود.وقتی از پارامترها برای مقادیر ورودی در کوئری استفاده میکنید، Django یا کتابخانهی مربوطه مقدار ورودی شما را ایمنسازی میکند. این یعنی کاراکترهای مخربی که ممکن است توسط یک مهاجم وارد شوند، بهعنوان بخشی از داده در نظر گرفته شده و نمیتوانند ساختار اصلی کوئری را تغییر دهند. به این فرآیند "escaping" گفته میشود.
اگر مستقیماً مقادیر کاربر را بدون استفاده از پارامترها در رشتهی SQL قرار دهید، کوئری شما در برابر SQL Injection آسیبپذیر میشود.
به عنوان مثال ناامن، فرض کنید کاربر میخواهد محصولی را براساس قیمت جستجو کند:
price = input("Enter a price: ")
query = f"SELECT * FROM products WHERE price > {price}"
cursor.execute(query)
اگر کاربر به جای مقدار عددی، ورودی مخربی مثل زیر وارد کند:
0; DROP TABLE products; --
کوئری نهایی شما به شکل زیر خواهد بود:
SELECT * FROM products WHERE price > 0; DROP TABLE products; --
این کوئری باعث حذف شدن جدول products میشود!