tgoop.com/djangolearn_ir/785
Create:
Last Update:
Last Update:
کوئری raw زدن در #جنگو
درسته #django یک ORM خوب داره و تقریبا تمام چیزهایی که لازم دارید رو ساپورت میکنه اما شما میتونید داخل جنگو مستقیم کوئری SQL ران کنید!
ران کردن این کوئریها به صورت raw میتونه تو دو لایه در جنگو انجام بشه. یک در لایه مدل خودتون و دومی تو لایه پایین تر مستقیم با کانکشن دیتابیس.
تو حال اول جنگو سعی میکنه که خروجی SQL را براتون Map کنه و خروجی دوباره مدل براتون برگردونه حتی وقتی دارید raw میزنید مثال:
مدل فرضی:
class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)
کوئری مثال:
Person.objects.raw("SELECT * FROM myapp_person")
این کوئری دقیقا معادل objects.all() و جنگو خروجی رو بر اساس اسم فیلدها مپ میکنه به مدل. این مهمه ها! بر اساس اسم فیلد! یعنی شما میتونید کوئری رو حتی رو یک تیبل دیگه بزنید و تا زمانی که اسم فیلدا خروجیتون با مدل یکی باشه جنگو اونهارو مپ میکنه. مثال:
>>> Person.objects.raw(
... """
... SELECT first AS first_name,
... last AS last_name,
... bd AS birth_date,
... pk AS id,
... FROM some_other_table
... """
... )
بله میتونیم از AS استفاده کنیم و اسم فیلدا مشابه مدلمون بزاریم. خود جنگو هم یک فیچر داره که براتون همین AS رو میزنه!
>>> name_map = {"first": "first_name", "last": "last_name", "bd": "birth_date", "pk": "id"}
>>> Person.objects.raw("SELECT * FROM some_other_table", translations=name_map)
میتونید از پارامتر translations استفاده کنید برای اینکار.
میتونید برخی از فیلدها رو انتخاب نکنید!
برای مثال:
>>> for p in Person.objects.raw("SELECT id, first_name FROM myapp_person"):
... print(
... p.first_name, # This will be retrieved by the original query
... p.last_name, # This will be retrieved on demand
... )
...
برای مثال داخل این raw کوئری ما فیلد last_name رو انتخاب نکردیم. حالا چه اتفاقی افتاده؟ همچنان اگه شما فیلد last_name صدا بزنید مشکلی پیش نمیاد و دریافتش میکنید ولیییییی جنگو از اونجایی که اون فیلد داخل کوئری وارد نکرده بودید و خروجیش رو نداشته خودش میاد همون لحضه دوباره یک درخواست به دیتابیس میزنه و اون دریافت میکنه!
لایه خود کانکشن
اگه این مپینگ رو نمیخایید و کلا میخوایید یک کوئری مستقیم بزنید مثل زمانی که از یک کتابخونه معمولی تو پایتون برای دیتابیس استفاده میکنید میتونید از connection در جنگو استفاده کنید! مثال:
from django.db import connection
def my_custom_sql(self):
with connection.cursor() as cursor:
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
خروجی یک لیست از نتایج خواهد بود. البته میتونید با یک حرکت ساده این لیست مپ کنید خودتون و در نهایت یک دیکشنری داشته باشید.
def dictfetchall(cursor):
"""
Return all rows from a cursor as a dict.
Assume the column names are unique.
"""
columns = [col[0] for col in cursor.description]
return [dict(zip(columns, row)) for row in cursor.fetchall()]
و آخرین نکته اینکه وقتی دارید از raw استفاده میکنید دیگه اسلایس کردن رو لول کوئری لیمیت نمیزاره و بهتره از LIMIT استفاده کنید داخل خود کوئری SQL
@TorhamDevCH
BY جنگولرن
Share with your friend now:
tgoop.com/djangolearn_ir/785