TorhamDev | تورهام 😳 – Telegram
TorhamDev | تورهام 😳
2.84K subscribers
420 photos
49 videos
21 files
591 links
code, linux and anything related.

• YouTube
youtube.com/@techwithtori

• CodeNaline Podcast
@CodeNaline

• Group
@GothamProgrammers

• Github
github.com/TorhamDev

• Email
torhamdev@gmail.com
Download Telegram
Media is too big
VIEW IN TELEGRAM
Learn PostgreSQL Tutorial - Full Course for Beginners

دانلود کرده بودم برای مصارف شخصی گفتم شاید به دردتون بخوره. نسخه یوتیوبش هست. این برای اونایی که نت درست و درمون ندارن.
15
Forwarded from Sadra Codes
توی نسخه 0.6.3 پای‌اکشن، سرعت اجرای اکشن به دلیل Dependency Management بهینه‌تر، بهبود پیدا کرده و سریعتر شده.

و اینکه خروجی کامند pyaction run تمیزتر و بهتر شده. :))


More >> https://pyaction.imsadra.me/
1👍1
شاید برای شما هم سوال بود که چطور SQL کوئری‌هایی که با ORM جنگو میزنیم رو ببینیم؟

https://b0uh.github.io/django-show-me-the-sql.html

@TorhamDevCH
👍41
به نظرم یکی از بهترین اسکیل(مهارت؟)هایی که به عنوان یک برنامه‌نویس میتونید داشته باشید، توانایی تحقیق و جست‌وجو، یعنی چی؟
یعنی وقتی یک سوالی براتون پیش میاد سریع نرید دنبال اینکه جواب چیه. منظورم اینه که بدون درک کردن جواب صرفا جواب بدونید. مثل اون موقع‌هایی که داری گیم بازی میکنی تو یک مرحله میمونی و گوگل و بقیه جاهارو میگردی که فقط مرحله رو رد کنی، دقیقا هرکاری که طرف میکنه رو انجام میدی تا مرحله رو رد کنی:).
ولی خب شاید بهتر بود از همون اول دیالوگ NPCهارو میخوندی XD.
موضوع اینه که آدم فضایی‌ها نمیان به اون آدم‌ها بگن که چطوری اون مرحله کار میکنه یا راه حل فلان مشکل چیه، اون آدم‌ها صرفا انقدر صبور و کنجکاو بودن که دیالوگ NPCها رو بخونن. در نتیجه شماهم اگه سعی کنی دفعه بعد که مشکلی رو خوردید به جای جواب مستقیم به سمت جواب غیر مستقیم برید و اول موضوع و مشکل رو درک کنید احتمالا خیلی چیزهای بیشتری یاد میگیرید.

روشش هم ساده است.
به یک مشکل میخورید، مثلا ارور، اینجا دوتا مسیر پیش‌رو داریم.
مسیر اول ارور کپی میکنی گوگل یا این‌روزا با کلاس‌ترها GPTمیکنن و جواب مستقیم در میارید دوتا خط کد هم کپی میکنید یا تغییر میدید و پایان.

مسیر دوم: نوع ارور رو گوگل میکنید و سعی میکنید بفهمید اصلا چرا همچین اروری رخ میده، چه دلایلی هست که باعث این ارور میشه، اون دلیل اولی خودش چرا اتفاق میوفته؟ یکهو میفهمید کامپیوترا فلان چیز این‌شکلی هندل میکنن برای همون که شما این رو ایشکلی دادید بهش نتونسته هندل کنه و ارور خوردید، همینطوری پیش میرید و به یک دریا بینهایت از محتوا و دانش دست پیدا میکنید :)
خلاصه سعی ‌کنید ماهیگیری یادبگیرید.

@TorhamDevCH
👍15🔥11❤‍🔥11
ایونت لوپ چیست؟ درسته داخل js توضیح میده ولی این مفهوم همجا یک چیزه ما داخل Async پایتون هم ایونت لوپ رو داریم. و البته که یکم js یادگرفتن بد نیست :)

اگه یک نفر اینطوری js یاد میده، من برم js دولوپر شم 😂💔

https://www.youtube.com/watch?v=8aGhZQkoFbQ
👍1
یک نکته درباره primary key داخل #جنگو اینه که شما میتونید برای هر app به شکل خاص primary key خاص خودش رو داشته باشید. مثلا برای یک app از big integer استفاده کنید و برای یکی از UUID این رفتار رو برای هر اپ میتونید به مشخص کردن AppConfig.default_auto_field مشخص کنید. حالا #django این قابلیت رو هم بهتون میده که جدا از انتخاب دونه دونه برای هر اپ یک حالت گلوبال در نظر بگیرید که اگر مخصوص اپ ست نکرده باشید از اون استفاده میکنه که پیش‌فرض خود جنگو BigIntegerField در نظر میگیره و میشه با تغییر دادن DEFAULT_AUTO_FIELD داخل settings.py به شکل گلوبال تغییرش داد

@TorhamDevCH
❤‍🔥22👍2
TorhamDev | تورهام 😳
یک نکته درباره primary key داخل #جنگو اینه که شما میتونید برای هر app به شکل خاص primary key خاص خودش رو داشته باشید. مثلا برای یک app از big integer استفاده کنید و برای یکی از UUID این رفتار رو برای هر اپ میتونید به مشخص کردن AppConfig.default_auto_field…
این توانایی که خود #جنگو بهتون میده ولی از trick دیگه هم میتونید استفاده کنید و اون هم ساختن یک مدل ابسترکت و بقیه مدل‌ها ازش ارث ببرن.
مثال:

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
41👍1
کوئری‌های #جنگو lazy هستند

اما این یعنی چی؟ کلا برای فهمیدن موضوع 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
6👍2
خب من یک چیز خیلی جالب و در این حال گیج‌کننده درباره ORM #جنگو فهمیدم.

تو پیام قبلی گفتم که کوئری‌های #django دقیقا چه زمانی واقعا اجرا میشن. اما اینجا یک نکته دیگه‌ای هم هست، جنگو نتیجه کوئری‌هارو کش میکنه.

و این خیلیییییییییییی مهمه، یعنی بعضی از جاها که فکر میکنید جنگو قرار دیتابیس هیت کنه هیت نمیکنه و از کش استفاده میکنه و بعضی جاها که فکر میکنید قرار کش استفاده کنه واقعا هیت میکنه. دونستن و فهمیدن این که چه زمانی کش استفاده میکنه چه زمانی نه حدود ۲ ساعت از من زمان گرفت :) ولی تو این پست توضیح میدم چیزی که فهمیدم رو.

اول این قانون تو ذهنتون داشته باشید: هر چیزی که باعث ایجاد یک QuerySet جدید بشه، باعث هیت به دیتابیس خواهد شد اگر اون کوئری اجرا بشه.

به مثال زیر دقت کنید:

users = User.objects.all()
print(users)

if users:
for u in users:
print(u)


خب تو این مثال فکر میکنید چندبار دیتابیس توسط جنگو هیت میشه؟ اگه ماجرا کش کردن ندونید ولی ماجرا اینکه چه زمانی واقعا اجرا میشه رو بدونید احتمالا با خودتون میگید ۳ بار داخل این کد جنگو دیتابیس رو هیت میکنه.

اما اگر من بگم فقط دو بار دیتابیس هیت میکنه چی؟

بزارید توضیح بدم. تو خط اول ما صرفا کوئری رو ساختیم و هیچ هیتی به دیتابیس نزدیم. تو خط دوم ما کوئری پرینت کردیم و اینجا اولین هیت به دیتابیس خورده میشه، ولی یک نکته اینجاست وقتی شما یک کوئری رو پرینت میکنید جنگو نمیاد کل کوئری رو اجرا کنه چون منطقی نیست!، مثلا اگر کوئری شما هزارتا خروجی داشته باشه شما اون هزارتا رو که داخل پرینت نمیخایید، در نتیجه جنگو فقط یک بخش از کوئری رو ران میکنه یا به عبارت دیگه از LIMIT استفاده میکنه!. تو این خط هیچ کش کردنی اتفاق نمیوفته(جلوتر میگم چرا)

خط بعدی ما از if استفاده کردیم و اینجا یک هیت دیگه به دیتابیس میخوره اما این‌بار کل کوئری اجرا میشه و اینجاست که جنگو ریزالت کوئری میگیره و داخل کش ذخیره میکنه. تو خط بعدی که اومدیم حلقه زدیم روی کوئری جنگو دیگه نمیاد به دیتابیس درخواست بزنه و از کش استفاده میکنه!

در نتیجه اینجا فقط ۲ بار دیتابیس هیت میخوره.

ادامه داخل پیام بعد...

@TorhamDevCH
👍11❤‍🔥3🆒21
TorhamDev | تورهام 😳
خب من یک چیز خیلی جالب و در این حال گیج‌کننده درباره ORM #جنگو فهمیدم. تو پیام قبلی گفتم که کوئری‌های #django دقیقا چه زمانی واقعا اجرا میشن. اما اینجا یک نکته دیگه‌ای هم هست، جنگو نتیجه کوئری‌هارو کش میکنه. و این خیلیییییییییییی مهمه، یعنی بعضی از جاها…
خب از ماجرا و گفته‌های خود داکیومنت جنگو میتونیم نتیجه بگیریم که جنگو زمانی یک ریزالت یک کوئری رو کش میکنه که کوئری کاملا اجرا بشه. یعنی داخل پرینت که بخشیش فقط اجرا شد کش اتفاق نمیوفته ولی داخل if کش اتفاق میوفته.
حالا شاید براتون سوال بشه کش رو چطوری میشه دید؟ میتونید با استفاده از _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
👍7🆒41
یک مبحثی که خیلی وقت‌ها آدم‌های رو داخل #جنگو گیج میکنه موضوع Aggregation هستش. برای مثال کوئری پایین:


>>> 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
👍731🌚1
If you think you're perfect already, then you never will be.

—Cristiano Ronaldo
11👍1
توصیه خود #جنگو اینه که آقا اگه به کوئریت شک داری احساس میکنی مقدار اشتباه داره میده یا اینی که نوشتی نتیجه‌اش اون SQL که میخواستی نشده، بشین ببین واقعا چه کوئری SQL ای ساخته که اینکه چطور این کار کنید تو یکی از پست‌ها بالا گفته بودم.

@TorhamDevCH
👍2
شاید برای شما هم سوال بود که چطور SQL کوئری‌هایی که با ORM جنگو میزنیم رو ببینیم؟

https://b0uh.github.io/django-show-me-the-sql.html

@TorhamDevCH
❤‍🔥2
چطوری داخل #جنگو 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
👍8
وقتی که بعد از پنج ساعت توضیح طرف، نفهمیدم مشکلش چیه، ولی بلاخره کدش رو فرستاد🗿🤝

با من با کد صحبت کن من دیگر زبان انسان‌ها را فراموش کرده ام

@TorhamDevCH
🤓8🤪2👍1👌1
کوئری 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.denoscription]
return [dict(zip(columns, row)) for row in cursor.fetchall()]


و‌ آخرین نکته اینکه وقتی دارید از raw استفاده میکنید دیگه اسلایس کردن رو لول کوئری لیمیت نمیزاره و بهتره از LIMIT استفاده کنید داخل خود کوئری SQL

@TorhamDevCH
👍92🔥1
دوسِتان ایا پست‌های جنگو برایتان مفید است؟
Anonymous Poll
79%
بله
21%
خیر
👍7❤‍🔥1