هیچی دیگه همچی داشت یادم میرفت گفتم اینجا بزارم قبل هر مصاحبه بخونم :)
تورهام 😳 | Django Tips pinned «هیچی دیگه همچی داشت یادم میرفت گفتم اینجا بزارم قبل هر مصاحبه بخونم :)»
Forwarded from TorhamDev | تورهام 😳
سوال جنگویی:
اگه یک مدل داشته باشیم به شکل زیر:
بعد بیاییم این کد رو اجرا کنیم:
اومدیم یک آبجکت ساختیم و ذخیره اش کردیم. بعد فیلم name که پرایمریکی بود رو آپدیت کردیم و ذخیرش کردیم.
حالا سوال اینه، در این لحظه چه اتفاقی میوفته؟ آیا ارور میخوریم یا ابجکت آپدیت میشه یا اتفاق دیگه ای میوفته؟
@TorhamDevCH
اگه یک مدل داشته باشیم به شکل زیر:
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
بعد بیاییم این کد رو اجرا کنیم:
>>> fruit = Fruit.objects.create(name="Apple")
>>> fruit.name = "Pear"
>>> fruit.save()
اومدیم یک آبجکت ساختیم و ذخیره اش کردیم. بعد فیلم name که پرایمریکی بود رو آپدیت کردیم و ذخیرش کردیم.
حالا سوال اینه، در این لحظه چه اتفاقی میوفته؟ آیا ارور میخوریم یا ابجکت آپدیت میشه یا اتفاق دیگه ای میوفته؟
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
TorhamDev | تورهام 😳
سوال جنگویی: اگه یک مدل داشته باشیم به شکل زیر: from django.db import models class Fruit(models.Model): name = models.CharField(max_length=100, primary_key=True) بعد بیاییم این کد رو اجرا کنیم: >>> fruit = Fruit.objects.create(name="Apple") >>> fruit.name…
اتفاقی که میوفته اینه که از اونجایی که فیلد name پرایمریکی و پرایمریکی ها Read-Only هستن شما نمیتونی آپدیتش کنی و اگه تلاش برای آپدیت کردنش کنی، جنگو میاد یک آبجکت جدید میسازه دقیقا با همون اطلاعات قبلی ولی فقط پرایمریکی رو تغییر میده. در نهایت شما دوتا آبجکت Fruit خواهید داشت.
@TorhamDevCH
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
داخل جنگو ۳ نوع Model inheritance داریم. یعنی مدلهای دیتابیس میتونن به سه شکل از هم دیگه ارث بری کنند.
۱. Abstract base classes
۲. Multi-table inheritance
۳. Proxy models
که فعلا با دوتا اول کار ندارم و احتمالا بدونید چی هستند. ولی سومی همیشه برای من گنگ بود که چی هست و چیکار میکنه. ولی داشتم داکیومنت جنگو میخوندم که رسیدم به توضیح پروکسیمدل و تمام، بهترین توضیحی بود که خوندم و تا آخر یادم خواهد ماند :)
if you only want to modify the Python-level behavior of a model, without changing the models fields in any way, you can use Proxy models.
اگر فقط و فقط میخوایید تو لول فانکشنالیتی مدل تغییر ایجاد کنید. مثلا فانکش foobar میخایید یک تغییر بدید برای نسخه جدید ولی میخوایید نسخه قدیمی باقی بمونه میایید از پروکسی استفاده میکنید.
حالا شما یک مدل دارید دقیقا با همون مشخصات ولی فانکشنالیتی فانکشن foobar فرق میکنه.
تو مثال خود داکیومنت یک فانکشنالیتی اضافه کرده:
@TorhamDevCH
۱. Abstract base classes
۲. Multi-table inheritance
۳. Proxy models
که فعلا با دوتا اول کار ندارم و احتمالا بدونید چی هستند. ولی سومی همیشه برای من گنگ بود که چی هست و چیکار میکنه. ولی داشتم داکیومنت جنگو میخوندم که رسیدم به توضیح پروکسیمدل و تمام، بهترین توضیحی بود که خوندم و تا آخر یادم خواهد ماند :)
if you only want to modify the Python-level behavior of a model, without changing the models fields in any way, you can use Proxy models.
اگر فقط و فقط میخوایید تو لول فانکشنالیتی مدل تغییر ایجاد کنید. مثلا فانکش foobar میخایید یک تغییر بدید برای نسخه جدید ولی میخوایید نسخه قدیمی باقی بمونه میایید از پروکسی استفاده میکنید.
حالا شما یک مدل دارید دقیقا با همون مشخصات ولی فانکشنالیتی فانکشن foobar فرق میکنه.
تو مثال خود داکیومنت یک فانکشنالیتی اضافه کرده:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
TorhamDev | تورهام 😳
داخل جنگو ۳ نوع Model inheritance داریم. یعنی مدلهای دیتابیس میتونن به سه شکل از هم دیگه ارث بری کنند. ۱. Abstract base classes ۲. Multi-table inheritance ۳. Proxy models که فعلا با دوتا اول کار ندارم و احتمالا بدونید چی هستند. ولی سومی همیشه برای من گنگ…
یک نکته رو باید در نظر داشته باشید که ساخت یک مدل پروکسی یک تیبل جدید داخل دیتابیس نمیسازه و از همون مدل قبلی استفاده خواهد کرد. تو این مثال مدل MyPerson دقیقا روی همون تیبل دیتابیسی که مدل Person کار میکنه کار خواهد کرد، پس اگه یک چیزی رو اپدیت کنید و بسازید و ... روی همون تیبل دیتابیسی انجام میدید که اگر با Person انجام میدادید.
@TorhamDevCH
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
شاید برای شما هم سوال بود که چطور SQL کوئریهایی که با ORM جنگو میزنیم رو ببینیم؟
https://b0uh.github.io/django-show-me-the-sql.html
@TorhamDevCH
https://b0uh.github.io/django-show-me-the-sql.html
@TorhamDevCH
b0uh.github.io
Django: show me the SQL - Thomas Loiret - Random thoughts
8 different ways to see the SQL generated by Django
Forwarded from TorhamDev | تورهام 😳
یک نکته درباره primary key داخل #جنگو اینه که شما میتونید برای هر app به شکل خاص primary key خاص خودش رو داشته باشید. مثلا برای یک app از big integer استفاده کنید و برای یکی از UUID این رفتار رو برای هر اپ میتونید به مشخص کردن AppConfig.default_auto_field مشخص کنید. حالا #django این قابلیت رو هم بهتون میده که جدا از انتخاب دونه دونه برای هر اپ یک حالت گلوبال در نظر بگیرید که اگر مخصوص اپ ست نکرده باشید از اون استفاده میکنه که پیشفرض خود جنگو BigIntegerField در نظر میگیره و میشه با تغییر دادن DEFAULT_AUTO_FIELD داخل settings.py به شکل گلوبال تغییرش داد
@TorhamDevCH
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
TorhamDev | تورهام 😳
یک نکته درباره primary key داخل #جنگو اینه که شما میتونید برای هر app به شکل خاص primary key خاص خودش رو داشته باشید. مثلا برای یک app از big integer استفاده کنید و برای یکی از UUID این رفتار رو برای هر اپ میتونید به مشخص کردن AppConfig.default_auto_field…
این توانایی که خود #جنگو بهتون میده ولی از trick دیگه هم میتونید استفاده کنید و اون هم ساختن یک مدل ابسترکت و بقیه مدلها ازش ارث ببرن.
مثال:
از اونجایی که اگه داخل مدل #django فیلدی داشته باشید که داخلش primary_key مقدار True داشته باشه جنگو دیگه از اون مقدار دیفالتی که مشخص کردید (هردو حالت دو پیام بالا) استفاده نمیکنه و میاد از این فیلد استفاده میکنه. حالا شما میتونید بقیه مدلهاتون رو از این مدل ارث بری کنید و دیگه نگران مقدار id نباشید.
@TorhamDevCH
مثال:
from django.db import models
from uuid import uuid4
class Base(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
class Meta:
abstract = True
از اونجایی که اگه داخل مدل #django فیلدی داشته باشید که داخلش primary_key مقدار True داشته باشه جنگو دیگه از اون مقدار دیفالتی که مشخص کردید (هردو حالت دو پیام بالا) استفاده نمیکنه و میاد از این فیلد استفاده میکنه. حالا شما میتونید بقیه مدلهاتون رو از این مدل ارث بری کنید و دیگه نگران مقدار id نباشید.
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
کوئریهای #جنگو lazy هستند
اما این یعنی چی؟ کلا برای فهمیدن موضوع lazy فکر کنم این ویدیو شهریار شریعتی (Laziness in Python تنبلی در پایتون ) خوب باشه و بتونید بفهمیدش، یا اینکه نسخه انگلیسی از Computerphile.
به این مثال توجه کنید:
این مثال خود داکیومنت جنگوعه. اینجا با ۳ تا کوئری زدیم و یکچیزی از دیتابیس درخواست کردیم، حالت عادی با خودتون میگید خب الان ۳ بار دیتابیس hit شده (درخواست رفته براش) اما در حقیقت فقط یک بار دیتابیس هیت شده و اون هم تو خط آخر جایی که کوئری رو پرینت کردیم. جنگو تنها و تنها زمانی دیتابیس رو با کوئری که شما زدید hit میکنه که دیتا رو درخواست کرده باشید. حالا چه پرینت باشه چه حلقه بزنید روش و ... و این نتیجه لیزی بودن کوئری هاست. تو کد بالا در حقیقت خط اول یک کوئری ساختیم، خط دوم یک فیلتر به همون کوئری اضافه کردیم و در نتیجه یک کوئری جدید ساخته شده و خط سوم هم همینطور و در نهااااااااااایت در خط چهارم یک کوئری به دیتابیس زدیم که داخش گفته هدلاین با what شروع شده باشه تاریخ پابلیش کوچیکتر از امروز باشه اونایی رو میخام که داخل بدنه شو کلمه food وجود داره.
@TorhamDevCH
اما این یعنی چی؟ کلا برای فهمیدن موضوع lazy فکر کنم این ویدیو شهریار شریعتی (Laziness in Python تنبلی در پایتون ) خوب باشه و بتونید بفهمیدش، یا اینکه نسخه انگلیسی از Computerphile.
به این مثال توجه کنید:
>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)
این مثال خود داکیومنت جنگوعه. اینجا با ۳ تا کوئری زدیم و یکچیزی از دیتابیس درخواست کردیم، حالت عادی با خودتون میگید خب الان ۳ بار دیتابیس hit شده (درخواست رفته براش) اما در حقیقت فقط یک بار دیتابیس هیت شده و اون هم تو خط آخر جایی که کوئری رو پرینت کردیم. جنگو تنها و تنها زمانی دیتابیس رو با کوئری که شما زدید hit میکنه که دیتا رو درخواست کرده باشید. حالا چه پرینت باشه چه حلقه بزنید روش و ... و این نتیجه لیزی بودن کوئری هاست. تو کد بالا در حقیقت خط اول یک کوئری ساختیم، خط دوم یک فیلتر به همون کوئری اضافه کردیم و در نتیجه یک کوئری جدید ساخته شده و خط سوم هم همینطور و در نهااااااااااایت در خط چهارم یک کوئری به دیتابیس زدیم که داخش گفته هدلاین با what شروع شده باشه تاریخ پابلیش کوچیکتر از امروز باشه اونایی رو میخام که داخل بدنه شو کلمه food وجود داره.
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
خب من یک چیز خیلی جالب و در این حال گیجکننده درباره ORM #جنگو فهمیدم.
تو پیام قبلی گفتم که کوئریهای #django دقیقا چه زمانی واقعا اجرا میشن. اما اینجا یک نکته دیگهای هم هست، جنگو نتیجه کوئریهارو کش میکنه.
و این خیلیییییییییییی مهمه، یعنی بعضی از جاها که فکر میکنید جنگو قرار دیتابیس هیت کنه هیت نمیکنه و از کش استفاده میکنه و بعضی جاها که فکر میکنید قرار کش استفاده کنه واقعا هیت میکنه. دونستن و فهمیدن این که چه زمانی کش استفاده میکنه چه زمانی نه حدود ۲ ساعت از من زمان گرفت :) ولی تو این پست توضیح میدم چیزی که فهمیدم رو.
اول این قانون تو ذهنتون داشته باشید: هر چیزی که باعث ایجاد یک QuerySet جدید بشه، باعث هیت به دیتابیس خواهد شد اگر اون کوئری اجرا بشه.
به مثال زیر دقت کنید:
خب تو این مثال فکر میکنید چندبار دیتابیس توسط جنگو هیت میشه؟ اگه ماجرا کش کردن ندونید ولی ماجرا اینکه چه زمانی واقعا اجرا میشه رو بدونید احتمالا با خودتون میگید ۳ بار داخل این کد جنگو دیتابیس رو هیت میکنه.
اما اگر من بگم فقط دو بار دیتابیس هیت میکنه چی؟
بزارید توضیح بدم. تو خط اول ما صرفا کوئری رو ساختیم و هیچ هیتی به دیتابیس نزدیم. تو خط دوم ما کوئری پرینت کردیم و اینجا اولین هیت به دیتابیس خورده میشه، ولی یک نکته اینجاست وقتی شما یک کوئری رو پرینت میکنید جنگو نمیاد کل کوئری رو اجرا کنه چون منطقی نیست!، مثلا اگر کوئری شما هزارتا خروجی داشته باشه شما اون هزارتا رو که داخل پرینت نمیخایید، در نتیجه جنگو فقط یک بخش از کوئری رو ران میکنه یا به عبارت دیگه از LIMIT استفاده میکنه!. تو این خط هیچ کش کردنی اتفاق نمیوفته(جلوتر میگم چرا)
خط بعدی ما از if استفاده کردیم و اینجا یک هیت دیگه به دیتابیس میخوره اما اینبار کل کوئری اجرا میشه و اینجاست که جنگو ریزالت کوئری میگیره و داخل کش ذخیره میکنه. تو خط بعدی که اومدیم حلقه زدیم روی کوئری جنگو دیگه نمیاد به دیتابیس درخواست بزنه و از کش استفاده میکنه!
در نتیجه اینجا فقط ۲ بار دیتابیس هیت میخوره.
ادامه داخل پیام بعد...
@TorhamDevCH
تو پیام قبلی گفتم که کوئریهای #django دقیقا چه زمانی واقعا اجرا میشن. اما اینجا یک نکته دیگهای هم هست، جنگو نتیجه کوئریهارو کش میکنه.
و این خیلیییییییییییی مهمه، یعنی بعضی از جاها که فکر میکنید جنگو قرار دیتابیس هیت کنه هیت نمیکنه و از کش استفاده میکنه و بعضی جاها که فکر میکنید قرار کش استفاده کنه واقعا هیت میکنه. دونستن و فهمیدن این که چه زمانی کش استفاده میکنه چه زمانی نه حدود ۲ ساعت از من زمان گرفت :) ولی تو این پست توضیح میدم چیزی که فهمیدم رو.
اول این قانون تو ذهنتون داشته باشید: هر چیزی که باعث ایجاد یک QuerySet جدید بشه، باعث هیت به دیتابیس خواهد شد اگر اون کوئری اجرا بشه.
به مثال زیر دقت کنید:
users = User.objects.all()
print(users)
if users:
for u in users:
print(u)
خب تو این مثال فکر میکنید چندبار دیتابیس توسط جنگو هیت میشه؟ اگه ماجرا کش کردن ندونید ولی ماجرا اینکه چه زمانی واقعا اجرا میشه رو بدونید احتمالا با خودتون میگید ۳ بار داخل این کد جنگو دیتابیس رو هیت میکنه.
اما اگر من بگم فقط دو بار دیتابیس هیت میکنه چی؟
بزارید توضیح بدم. تو خط اول ما صرفا کوئری رو ساختیم و هیچ هیتی به دیتابیس نزدیم. تو خط دوم ما کوئری پرینت کردیم و اینجا اولین هیت به دیتابیس خورده میشه، ولی یک نکته اینجاست وقتی شما یک کوئری رو پرینت میکنید جنگو نمیاد کل کوئری رو اجرا کنه چون منطقی نیست!، مثلا اگر کوئری شما هزارتا خروجی داشته باشه شما اون هزارتا رو که داخل پرینت نمیخایید، در نتیجه جنگو فقط یک بخش از کوئری رو ران میکنه یا به عبارت دیگه از LIMIT استفاده میکنه!. تو این خط هیچ کش کردنی اتفاق نمیوفته(جلوتر میگم چرا)
خط بعدی ما از if استفاده کردیم و اینجا یک هیت دیگه به دیتابیس میخوره اما اینبار کل کوئری اجرا میشه و اینجاست که جنگو ریزالت کوئری میگیره و داخل کش ذخیره میکنه. تو خط بعدی که اومدیم حلقه زدیم روی کوئری جنگو دیگه نمیاد به دیتابیس درخواست بزنه و از کش استفاده میکنه!
در نتیجه اینجا فقط ۲ بار دیتابیس هیت میخوره.
ادامه داخل پیام بعد...
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
TorhamDev | تورهام 😳
خب من یک چیز خیلی جالب و در این حال گیجکننده درباره ORM #جنگو فهمیدم. تو پیام قبلی گفتم که کوئریهای #django دقیقا چه زمانی واقعا اجرا میشن. اما اینجا یک نکته دیگهای هم هست، جنگو نتیجه کوئریهارو کش میکنه. و این خیلیییییییییییی مهمه، یعنی بعضی از جاها…
خب از ماجرا و گفتههای خود داکیومنت جنگو میتونیم نتیجه بگیریم که جنگو زمانی یک ریزالت یک کوئری رو کش میکنه که کوئری کاملا اجرا بشه. یعنی داخل پرینت که بخشیش فقط اجرا شد کش اتفاق نمیوفته ولی داخل if کش اتفاق میوفته.
حالا شاید براتون سوال بشه کش رو چطوری میشه دید؟ میتونید با استفاده از _result_cache ببینیدش، اینطوری:
خروجی این خواهد بود: ( اگر فقط یک یوزر داشته باشیم)
همینطور که میبینید بعد از اجرا کردن پرینت رو کوئری کش هنوز None ( اینجا یکم شاید فهمیدنش سخت بشه با یکدونه یوزر ولی فکر کن هزارتا یوزر داریم پرینت فقط ۱۰ تاشو نشون خواهد داد)
پس بعد پرینت کش اتفاق نیوفتاد. ولی بعد از اینکه if اجرا شد کش پر شد و از اون به بعد جنگو از کش استفاده میکنه. البتهههههههه یک سری نکته هست که برمیگرده به قانونی که تو پست قبل گفتم. برای مثال:
تو این کد اینبار ۳ بار کوئری به دیتابیس میخوره. چرا؟ چون وقتی از .values استفاده میکنید یک QurySet جدید میسازید و اون کوئریست کش جدا خودش رو داره و از اونجایی که کشش خالیه در اون لحظه جنگو یک درخواست دیگه به دیتابیس خواهد زد :)
پایان\
@TorhamDevCH
حالا شاید براتون سوال بشه کش رو چطوری میشه دید؟ میتونید با استفاده از _result_cache ببینیدش، اینطوری:
users = User.objects.all()
print(users)
print("Cache: ", users._result_cache)
if users:
print("Cache: ", users._result_cache)
for u in users:
print(u)
خروجی این خواهد بود: ( اگر فقط یک یوزر داشته باشیم)
<QuerySet [<User: torham>]>
Cache: None
Cache: [<User: torham>]
torham
همینطور که میبینید بعد از اجرا کردن پرینت رو کوئری کش هنوز None ( اینجا یکم شاید فهمیدنش سخت بشه با یکدونه یوزر ولی فکر کن هزارتا یوزر داریم پرینت فقط ۱۰ تاشو نشون خواهد داد)
پس بعد پرینت کش اتفاق نیوفتاد. ولی بعد از اینکه if اجرا شد کش پر شد و از اون به بعد جنگو از کش استفاده میکنه. البتهههههههه یک سری نکته هست که برمیگرده به قانونی که تو پست قبل گفتم. برای مثال:
users = User.objects.all()
print(users)
if users:
for u in users.values("username"):
print(u)
تو این کد اینبار ۳ بار کوئری به دیتابیس میخوره. چرا؟ چون وقتی از .values استفاده میکنید یک QurySet جدید میسازید و اون کوئریست کش جدا خودش رو داره و از اونجایی که کشش خالیه در اون لحظه جنگو یک درخواست دیگه به دیتابیس خواهد زد :)
پایان\
@TorhamDevCH
Forwarded from TorhamDev | تورهام 😳
یک مبحثی که خیلی وقتها آدمهای رو داخل #جنگو گیج میکنه موضوع Aggregation هستش. برای مثال کوئری پایین:
خب این کوئری مشخصه چه کاری داره انجام میده، همه میتونن بفهمنش مخصوصا وقتی خروجی کوئری رو میبینن، اما اگر ازشون بپرسید خب Aggregation چی هستش هیچ ایده ای ندارن! و این ماجرا از ضعف در دانش SQL سر چشمه میگیره. چون خیلی از آدمهایی که دارن #django کار میکنن مستقیم سراغ جنگو اومدن و نرفتن چیزهای دیگه رو مطالعه کنن و یاد بگیرن.
اسم Aggregation داخل ORM جنگو مستقیما از SQL میاد. در SQL یک سری فانکشن وجود داره که بهشون Aggregation functions میگن و کارشون خلاصه سازی اطلاعات:
MIN() - returns the smallest value within the selected column
MAX() - returns the largest value within the selected column
COUNT() - returns the number of rows in a set
SUM() - returns the total sum of a numerical column
AVG() - returns the average value of a numerical column
و خب شما میتونید داخل کوئریهای SQL ازشون استفاده کنید و دیتا خروجی رو خلاصه سازی کنید و یا یک آمار ازش دربیارید. مثلا میانگین قیمت کتابهای تو سال اخیر و ...
یک کوئری مثال برای Aggregation میتونه این باشه:
خب از اونجایی که ORM جنگو در نهایت قرار کار همین SQL نوشتن برای شما انجام بده و کوئری شمارو به SQL تبدیل کنه شما دقیقا همین کوئری میتونید داخل جنگو به این صورت بنویسید:
میتونید لیست فانکشنهای Aggregation خود SQL داخل این لینک ببینید و ساپورت جنگو هم میتونید داخل این لینک ببینید.
در نهایت از دانش SQL غافل نباشید و حتما یادش بیگیرید. هرچی بیشتر SQL بدونید زندگی راحتتری خواهید داشت.
@TorhamDevCH
>>> from django.db.models import Avg, Max, Min
>>> Book.objects.aggregate(Avg("price"), Max("price"), Min("price"))
# {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
خب این کوئری مشخصه چه کاری داره انجام میده، همه میتونن بفهمنش مخصوصا وقتی خروجی کوئری رو میبینن، اما اگر ازشون بپرسید خب Aggregation چی هستش هیچ ایده ای ندارن! و این ماجرا از ضعف در دانش SQL سر چشمه میگیره. چون خیلی از آدمهایی که دارن #django کار میکنن مستقیم سراغ جنگو اومدن و نرفتن چیزهای دیگه رو مطالعه کنن و یاد بگیرن.
اسم Aggregation داخل ORM جنگو مستقیما از SQL میاد. در SQL یک سری فانکشن وجود داره که بهشون Aggregation functions میگن و کارشون خلاصه سازی اطلاعات:
MIN() - returns the smallest value within the selected column
MAX() - returns the largest value within the selected column
COUNT() - returns the number of rows in a set
SUM() - returns the total sum of a numerical column
AVG() - returns the average value of a numerical column
و خب شما میتونید داخل کوئریهای SQL ازشون استفاده کنید و دیتا خروجی رو خلاصه سازی کنید و یا یک آمار ازش دربیارید. مثلا میانگین قیمت کتابهای تو سال اخیر و ...
یک کوئری مثال برای Aggregation میتونه این باشه:
SELECT AVG(Price) as price_avg FROM Books WHERE puddate='2023-01-01';
خب از اونجایی که ORM جنگو در نهایت قرار کار همین SQL نوشتن برای شما انجام بده و کوئری شمارو به SQL تبدیل کنه شما دقیقا همین کوئری میتونید داخل جنگو به این صورت بنویسید:
>>> from django.db.models import Avg
>>> from datetime import datetime
>>> Books.objects.filter(pubdate=datetime(2023, 1, 1)).aggregate(price_avg=Avg("price"))
میتونید لیست فانکشنهای Aggregation خود SQL داخل این لینک ببینید و ساپورت جنگو هم میتونید داخل این لینک ببینید.
در نهایت از دانش SQL غافل نباشید و حتما یادش بیگیرید. هرچی بیشتر SQL بدونید زندگی راحتتری خواهید داشت.
@TorhamDevCH
W3Schools
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.
Forwarded from TorhamDev | تورهام 😳
چطوری داخل #جنگو manager رو rename کنیم؟
همه آپهای جنگو حداقل یک منیجر دارن که به صورت پیشفرض اون منیجیر objects خونده میشه و شما همچین استفاده ای ازش میکنید:
Users.objects.all()
اما شاید بخوایید از کلمه objects به عنوان فیلد استفاده کنید یا به هر دلیلی میخایید این اسم رو تغییر بدید. برای اینکار شما به راحتی میتونید یک فیلد داخل مدل جنگو بسازید و اون رو برابر با models.Manager() کنید با اینکار جنگو میاد objects رو حذف و از این فیلد استفاده میکنه و اگر بعد این کار شما سعی کنید از objects استفاده کنید ارور AttributeError میخورید.
مثال:
from django.db import models
class Person(models.Model):
# ...
people = models.Manager()
رو این مدل اگه objects رو صدا کنید ارور میخورید و برای کوئری زدن باید از people استفاده کنید.
Person.objects.all() ❌
Person.people.all() ✅
@TorhamDevCH
همه آپهای جنگو حداقل یک منیجر دارن که به صورت پیشفرض اون منیجیر objects خونده میشه و شما همچین استفاده ای ازش میکنید:
Users.objects.all()
اما شاید بخوایید از کلمه objects به عنوان فیلد استفاده کنید یا به هر دلیلی میخایید این اسم رو تغییر بدید. برای اینکار شما به راحتی میتونید یک فیلد داخل مدل جنگو بسازید و اون رو برابر با models.Manager() کنید با اینکار جنگو میاد objects رو حذف و از این فیلد استفاده میکنه و اگر بعد این کار شما سعی کنید از objects استفاده کنید ارور AttributeError میخورید.
مثال:
from django.db import models
class Person(models.Model):
# ...
people = models.Manager()
رو این مدل اگه objects رو صدا کنید ارور میخورید و برای کوئری زدن باید از people استفاده کنید.
Person.objects.all() ❌
Person.people.all() ✅
@TorhamDevCH