🔆کدنویسی تمیز:
خیلی وقتها برای فیلتر کردن یه لیست، ناخودآگاه میریم سراغ حلقههای تو در تو و کدهای طولانی. فرض کن یه لیست از کاربرها داری و فقط میخوای اونهایی که فعال هستن و سنشون بالای ۱۸ ساله رو جدا کنی. کد معمولی و شلوغ این شکلی میشه:
اما توی پایتون میشه همین کار رو خیلی تمیزتر، خواناتر و سریعتر با List Comprehension انجام داد:
با این ترفند ساده هم خوانایی کد بالا میره و هم تعداد خطوط کمتر میشه.
🐍 @python_rd
خیلی وقتها برای فیلتر کردن یه لیست، ناخودآگاه میریم سراغ حلقههای تو در تو و کدهای طولانی. فرض کن یه لیست از کاربرها داری و فقط میخوای اونهایی که فعال هستن و سنشون بالای ۱۸ ساله رو جدا کنی. کد معمولی و شلوغ این شکلی میشه:
active_adults = []
for user in users:
if user['is_active'] == True:
if user['age'] > 18:
active_adults.append(user)
اما توی پایتون میشه همین کار رو خیلی تمیزتر، خواناتر و سریعتر با List Comprehension انجام داد:
active_adults = [u for u in users if u['is_active'] and u['age'] > 18]
با این ترفند ساده هم خوانایی کد بالا میره و هم تعداد خطوط کمتر میشه.
🐍 @python_rd
👍3❤1
🔆بهینهسازی کوئری در جنگو
یکی از بزرگترین دلایل کند شدن پروژههای جنگویی، اجرای کوئریهای تکراری روی دیتابیسه که بهش چالش N+1 میگن. فرض کن میخوای لیست کتابها و نام نویسنده هر کتاب رو نمایش بدی. اگر کد رو اینطوری بنویسی، جنگو برای هر کتاب یه کوئری جداگانه به جدول نویسندهها میزنه:
برای حل این مشکل کافیه از select_related استفاده کنی تا جنگو با یک Joint ساده در دیتابیس، همه اطلاعات رو یکجا بکشه بیرون و سرعت لود صفحه رو چند برابر کنه:
همیشه قبل از دیپلوی کردن پروژه، تعداد کوئریهاتون رو با Django Debug Toolbar چک کنید تا سرور زیر بار نره.
🐍 @python_rd
یکی از بزرگترین دلایل کند شدن پروژههای جنگویی، اجرای کوئریهای تکراری روی دیتابیسه که بهش چالش N+1 میگن. فرض کن میخوای لیست کتابها و نام نویسنده هر کتاب رو نمایش بدی. اگر کد رو اینطوری بنویسی، جنگو برای هر کتاب یه کوئری جداگانه به جدول نویسندهها میزنه:
books = Book.objects.all()
for book in books:
print(book.author.name) # اجرای یک کوئری اضافه به ازای هر کتاب!
برای حل این مشکل کافیه از select_related استفاده کنی تا جنگو با یک Joint ساده در دیتابیس، همه اطلاعات رو یکجا بکشه بیرون و سرعت لود صفحه رو چند برابر کنه:
books = Book.objects.select_related('author').all()
for book in books:
print(book.author.name) # بدون کوئری اضافههمیشه قبل از دیپلوی کردن پروژه، تعداد کوئریهاتون رو با Django Debug Toolbar چک کنید تا سرور زیر بار نره.
🐍 @python_rd
👍2
🔆 مدیریت حافظه با استفاده از Generator در پایتون
🔹 برای کار با لیستهای خیلی بزرگ، استفاده از لیستکامپرهنشن معمولی باعث میشه تمام دادهها همزمان توی رم بارگذاری بشن که اصلاً بهینه نیست. با تغییر پرانتزها به براکت، میتونی از جنریتور استفاده کنی تا دادهها فقط موقع نیاز تولید بشن و مصرف حافظه برنامه به شدت کاهش پیدا کنه.
🐍 @python_rd
🔹 برای کار با لیستهای خیلی بزرگ، استفاده از لیستکامپرهنشن معمولی باعث میشه تمام دادهها همزمان توی رم بارگذاری بشن که اصلاً بهینه نیست. با تغییر پرانتزها به براکت، میتونی از جنریتور استفاده کنی تا دادهها فقط موقع نیاز تولید بشن و مصرف حافظه برنامه به شدت کاهش پیدا کنه.
# بد: مصرف حافظه بالا برای لیستهای حجیم
my_list = [x**2 for x in range(1000000)]
# خوب: مصرف حافظه ناچیز به صورت Lazy
my_gen = (x**2 for x in range(1000000))
🐍 @python_rd
❤3🔥1
🔆 تفاوت exists و count در کوئریستهای جنگو
🔹 برای چک کردن وجود یک رکورد در دیتابیس، خیلیها از count استفاده میکنن که باعث میشه دیتابیس تمام رکوردهای مشابه رو بشماره. این کار برای جدولهای بزرگ خیلی سنگینه. متد exists به محض پیدا کردن اولین مورد، متوقف میشه و سرعت اجرای برنامه رو به مراتب بالاتر میبره.
🐍 @python_rd
🔹 برای چک کردن وجود یک رکورد در دیتابیس، خیلیها از count استفاده میکنن که باعث میشه دیتابیس تمام رکوردهای مشابه رو بشماره. این کار برای جدولهای بزرگ خیلی سنگینه. متد exists به محض پیدا کردن اولین مورد، متوقف میشه و سرعت اجرای برنامه رو به مراتب بالاتر میبره.
# بد: بررسی کل جدول با count
if User.objects.filter(username="ali").count() > 0:
print("User exists")
# خوب: توقف بلافاصله بعد از پیدا کردن مورد با exists
if User.objects.filter(username="ali").exists():
print("User exists")
🐍 @python_rd
❤3
🔆کلاسهای پایتونی سبکتر با slots
🔹وقتی کلاسهای زیادی میسازی، پایتون برای هر نمونه یک دیکشنری اختصاصی ایجاد میکنه که کلی از رم سیستم رو بیدلیل اشغال میکنه. با تعریف slots توی کلاست، به پایتون دستور میدی که دیگه اون دیکشنری سنگین رو نسازه و فقط ویژگیهایی که نوشتی رو ذخیره کنه. این ترفند برای پروژههای بزرگ که با دیتای حجیم سروکار دارن، مثل یک معجزه برای کاهش مصرف رم عمل میکنه.
🐍 @python_rd
🔹وقتی کلاسهای زیادی میسازی، پایتون برای هر نمونه یک دیکشنری اختصاصی ایجاد میکنه که کلی از رم سیستم رو بیدلیل اشغال میکنه. با تعریف slots توی کلاست، به پایتون دستور میدی که دیگه اون دیکشنری سنگین رو نسازه و فقط ویژگیهایی که نوشتی رو ذخیره کنه. این ترفند برای پروژههای بزرگ که با دیتای حجیم سروکار دارن، مثل یک معجزه برای کاهش مصرف رم عمل میکنه.
class User:
slots = ['name', 'id']
def init(self, name, id):
self.name = name
self.id = id
🐍 @python_rd
🔥1
🔆 ترکیب دیکشنریها با عملگر |
احتمالا قبلا برای ادغام دو دیکشنری از متد update یا روشهای دیگه استفاده میکردی که کد رو شلوغ میکرد. حالا توی پایتون ۳.۹ به بعد، خیلی شیک میتونی با استفاده از عملگر پایپ یا همون | دو تا دیکشنری رو با هم ترکیب کنی. نتیجه یک دیکشنری جدیده که تمام محتویات قبلیها رو داره و خیلی هم سریعتر و خواناتر نوشته شده.
🐍 @python_rd
احتمالا قبلا برای ادغام دو دیکشنری از متد update یا روشهای دیگه استفاده میکردی که کد رو شلوغ میکرد. حالا توی پایتون ۳.۹ به بعد، خیلی شیک میتونی با استفاده از عملگر پایپ یا همون | دو تا دیکشنری رو با هم ترکیب کنی. نتیجه یک دیکشنری جدیده که تمام محتویات قبلیها رو داره و خیلی هم سریعتر و خواناتر نوشته شده.
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}
merged = dict1 | dict2
print(merged)
# خروجی: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
🐍 @python_rd
🔆 ۸ سایت رایگان برای تمرین پایتون
🔸 Practice Python:
تمرینهای ساده با پاسخ؛ عالی برای شروع.
🔸PyNative:
کوییز و تمرینهای مرحلهای + اجرای آنلاین.
🔸PyChallenger:
درسهای کوتاه + تمرین داخل مرورگر.
🔸LabEx:
تمرین تعاملی و سناریو محور برای مهارتسازی.
🔸Learn2Code:
تمرینهای سریع بدون نیاز به ثبتنام.
🔸Codewars:
چالشهای الگوریتمی (Kata) سطحبندیشده.
🔸HackerRank:
حل مسئله و آمادگی مصاحبه فنی.
🔸Project Euler:
مسائل ریاضی/محاسباتی برای سطح پیشرفته.
🐍 @python_rd
🔸 Practice Python:
تمرینهای ساده با پاسخ؛ عالی برای شروع.
🔸PyNative:
کوییز و تمرینهای مرحلهای + اجرای آنلاین.
🔸PyChallenger:
درسهای کوتاه + تمرین داخل مرورگر.
🔸LabEx:
تمرین تعاملی و سناریو محور برای مهارتسازی.
🔸Learn2Code:
تمرینهای سریع بدون نیاز به ثبتنام.
🔸Codewars:
چالشهای الگوریتمی (Kata) سطحبندیشده.
🔸HackerRank:
حل مسئله و آمادگی مصاحبه فنی.
🔸Project Euler:
مسائل ریاضی/محاسباتی برای سطح پیشرفته.
🐍 @python_rd
❤1
🔆 با پایتون چی میشه ساخت؟
پایتون فقط یک زبان برنامهنویسی نیست؛ یک جعبهابزار کامل برای ساخت تقریباً هر چیزیه! 🚀
🔹Pandas
برای تحلیل دادهها استفاده میشه.
🔹Scikit-learn
برای پیادهسازی یادگیری ماشین کاربرد داره.
🔹PyTorch
برای یادگیری عمیق و مدلهای هوش مصنوعی عالیه.
🔹TensorFlow
برای ساخت و توسعه مدلهای هوش مصنوعی استفاده میشه.
🔹Django
برای توسعه وبسایتهای حرفهای استفاده میشه.
🔹Flask
برای توسعه وبسایتهای سبک و سریع کاربرد داره.
🔹FastAPI
برای ساخت سریع API مورد استفاده قرار میگیره.
🔹NumPy
برای انجام محاسبات عددی پیچیده استفاده میشه.
🔹Matplotlib
برای مصورسازی دادهها و رسم نمودارها کاربرد داره.
🔹Beautiful Soup
برای وباسکرپینگ و جمعآوری اطلاعات از سایتها استفاده میشه.
🔹OpenCV
برای پردازش تصویر و بینایی ماشین استفاده میشه.
🔹NLTK
برای پردازش زبان طبیعی و متن کاربرد داره.
🔹Streamlit
برای ساخت سریع اپلیکیشنهای هوش مصنوعی استفاده میشه.
🔹Airflow
برای خودکارسازی و مدیریت فرایندها کاربرد داره.
🔹Apache Spark
برای پردازش کلانداده (Big Data) استفاده میشه.
🔹Kivy
برای ساخت اپلیکیشنهای دسکتاپ و موبایل کاربرد داره.
🔹AWS Boto3
برای اتوماسیون و مدیریت خدمات ابری AWS استفاده میشه.
🔹LangChain
برای ساخت ایجنتها و مدلهای هوش مصنوعی پیچیده کاربرد داره.
🔹Selenium
برای اتوماسیون فعالیتهای وب استفاده میشه.
🐍 @python_rd
پایتون فقط یک زبان برنامهنویسی نیست؛ یک جعبهابزار کامل برای ساخت تقریباً هر چیزیه! 🚀
🔹Pandas
برای تحلیل دادهها استفاده میشه.
🔹Scikit-learn
برای پیادهسازی یادگیری ماشین کاربرد داره.
🔹PyTorch
برای یادگیری عمیق و مدلهای هوش مصنوعی عالیه.
🔹TensorFlow
برای ساخت و توسعه مدلهای هوش مصنوعی استفاده میشه.
🔹Django
برای توسعه وبسایتهای حرفهای استفاده میشه.
🔹Flask
برای توسعه وبسایتهای سبک و سریع کاربرد داره.
🔹FastAPI
برای ساخت سریع API مورد استفاده قرار میگیره.
🔹NumPy
برای انجام محاسبات عددی پیچیده استفاده میشه.
🔹Matplotlib
برای مصورسازی دادهها و رسم نمودارها کاربرد داره.
🔹Beautiful Soup
برای وباسکرپینگ و جمعآوری اطلاعات از سایتها استفاده میشه.
🔹OpenCV
برای پردازش تصویر و بینایی ماشین استفاده میشه.
🔹NLTK
برای پردازش زبان طبیعی و متن کاربرد داره.
🔹Streamlit
برای ساخت سریع اپلیکیشنهای هوش مصنوعی استفاده میشه.
🔹Airflow
برای خودکارسازی و مدیریت فرایندها کاربرد داره.
🔹Apache Spark
برای پردازش کلانداده (Big Data) استفاده میشه.
🔹Kivy
برای ساخت اپلیکیشنهای دسکتاپ و موبایل کاربرد داره.
🔹AWS Boto3
برای اتوماسیون و مدیریت خدمات ابری AWS استفاده میشه.
🔹LangChain
برای ساخت ایجنتها و مدلهای هوش مصنوعی پیچیده کاربرد داره.
🔹Selenium
برای اتوماسیون فعالیتهای وب استفاده میشه.
🐍 @python_rd
❤2
This media is not supported in your browser
VIEW IN TELEGRAM
🔆 Insertion Sort
🔹 الگوریتم از عنصر دوم شروع میکنه، هر بار یک عدد رو بهعنوان key برمیداره، اعداد بزرگترِ بخش مرتبشده رو یک خانه به راست شیفت میده و key رو توی جای درستش قرار میده. این کار تا آخر آرایه ادامه پیدا میکنه تا کل لیست مرتب بشه.
کد:
🐍 @python_rd
🔹 الگوریتم از عنصر دوم شروع میکنه، هر بار یک عدد رو بهعنوان key برمیداره، اعداد بزرگترِ بخش مرتبشده رو یک خانه به راست شیفت میده و key رو توی جای درستش قرار میده. این کار تا آخر آرایه ادامه پیدا میکنه تا کل لیست مرتب بشه.
کد:
def insertion_sort(a):
n = len(a)
for i in range(1, n):
key = a[i]
j = i - 1
while j > 0 and a[j - 1] > key:
a[j] = a[j - 1]
j -= 1
a[j] = key
🐍 @python_rd
❤3
🔆 ترفند کوتاه پایتون: برعکس کردن لیست در یک خط
اگه بخوای یه لیست رو برعکس کنی، لازم نیست همیشه از reverse() استفاده کنی. و به جاش میتونی از این روش استفاده کنی:
🔹نکته مهم:
[::-1] یک کپیِ برعکسشده از لیست میسازه و لیست اصلی رو تغییر نمیده. و این تفاوت تو پروژههای واقعی خیلی مهم به درد میخوره، مخصوصا وقتی نخوای داده اصلی دستکاری شه.
🐍 @python_rd
اگه بخوای یه لیست رو برعکس کنی، لازم نیست همیشه از reverse() استفاده کنی. و به جاش میتونی از این روش استفاده کنی:
nums = [1, 2, 3, 4, 5]
reversed_nums = nums[::-1]
print(reversed_nums)
🔹نکته مهم:
[::-1] یک کپیِ برعکسشده از لیست میسازه و لیست اصلی رو تغییر نمیده. و این تفاوت تو پروژههای واقعی خیلی مهم به درد میخوره، مخصوصا وقتی نخوای داده اصلی دستکاری شه.
🐍 @python_rd
🔥4
🔆شمردن تعداد تکرار حروف در رشته
یکی از تمرینهای کاربردی واسه یادگیری دیکشنری تو پایتون، شمردن تعداد تکرار کاراکترها در یک رشته هست.
خروجی:
اگه رشته ما این باشه:
خروجی به این شکل میشه:
چرا از
چون ممکنه کلید هنوز داخل دیکشنری وجود نداشته باشه.
متد
یعنی:
- اگر
- اگر وجود نداشت،
بعد هم
این روش باعث میشه کد:
- تمیزتر باشه
- خواناتر باشه
- از شرطهای اضافه جلوگیری شه
🐍 @python_rd
یکی از تمرینهای کاربردی واسه یادگیری دیکشنری تو پایتون، شمردن تعداد تکرار کاراکترها در یک رشته هست.
text = "python"
result = {}
for ch in text:
result[ch] = result.get(ch, 0) + 1
print(result)
خروجی:
{'p': 1, 'y': 1, 't': 1, 'h': 1, 'o': 1, 'n': 1}اگه رشته ما این باشه:
text = "programming"
خروجی به این شکل میشه:
{'p': 1, 'r': 2, 'o': 1, 'g': 2, 'a': 1, 'm': 2, 'i': 1, 'n': 1}چرا از
get() استفاده کردیم؟چون ممکنه کلید هنوز داخل دیکشنری وجود نداشته باشه.
متد
get() اگه کلید رو پیدا نکنه، یه مقدار پیشفرض برمیگردونه.result.get(ch, 0)
یعنی:
- اگر
ch وجود داشت، مقدارش رو بده- اگر وجود نداشت،
0 بدهبعد هم
1 واحد بهش اضافه میکنیم.این روش باعث میشه کد:
- تمیزتر باشه
- خواناتر باشه
- از شرطهای اضافه جلوگیری شه
🐍 @python_rd
❤4👏1
🔆 enumerate()
تو پایتون به چه درد میخوره؟
🔹وقتی میخوای هم شمارهی آیتم رو داشته باشی، هم خود مقدار رو، لازم نیست با
خودت دردسر درست کنی.
تابع
این کار رو خیلی تمیز انجام میده.
🔹مثال:
🔹خروجی:
🔹اگر بخوای شمارش از 1 شروع بشه هم میتونی از آرگومان دوم استفاده کنی:
🔹خروجی:
🔹چرا مهمه؟
- کدت تمیزتر میشه
- خوانایی بالاتر میره
- از range(len(...)) بهتر و پایتونیکتره
🐍 @python_rd
تو پایتون به چه درد میخوره؟
🔹وقتی میخوای هم شمارهی آیتم رو داشته باشی، هم خود مقدار رو، لازم نیست با
range(len(...))
خودت دردسر درست کنی.
تابع
enumerate()
این کار رو خیلی تمیز انجام میده.
🔹مثال:
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
print(index, fruit)
🔹خروجی:
0 apple
1 banana
2 cherry
🔹اگر بخوای شمارش از 1 شروع بشه هم میتونی از آرگومان دوم استفاده کنی:
for index, fruit in enumerate(fruits, start=1):
print(index, fruit)
🔹خروجی:
1 apple
2 banana
3 cherry
🔹چرا مهمه؟
- کدت تمیزتر میشه
- خوانایی بالاتر میره
- از range(len(...)) بهتر و پایتونیکتره
🐍 @python_rd
❤6
🔆ساخت پسورد تصادفی با پایتون
🔹با ماژول secrets میتونی پسوردهای تصادفی و امن بسازی. این ماژول برای کارهای امنیتی، انتخاب بهتری نسبت به random محسوب میشه.
🔹هر بار که برنامه اجرا بشه، یک پسورد ۱۲ کاراکتری جدید ساخته میشه.
🐍 @python_rd
🔹با ماژول secrets میتونی پسوردهای تصادفی و امن بسازی. این ماژول برای کارهای امنیتی، انتخاب بهتری نسبت به random محسوب میشه.
import secrets
import string
characters = string.ascii_letters + string.digits + "!@#$%"
password = "".join(
secrets.choice(characters)
for _ in range(12)
)
print(password)
🔹هر بار که برنامه اجرا بشه، یک پسورد ۱۲ کاراکتری جدید ساخته میشه.
a8@Kp2#xQ9Lm
🐍 @python_rd
⚡2
🔆تفاوت == و is در پایتون
🔹توی پایتون، عملگر == مقدار دو متغیر رو مقایسه میکنه؛ اما is بررسی میکنه که آیا هر دو متغیر دقیقاً به یک آبجکت در حافظه اشاره میکنن یا نه.
🔹 خروجی:
🔹 مقدار numbers1 و numbers2 یکسانه، پس نتیجهی == برابر True میشه؛ اما این دو لیست، آبجکتهای جداگانهای هستن، پس نتیجهی is برابر False میشه.
🔹برای مقایسهی معمولی مقادیر از == استفاده کن. کاربرد رایج و درست is، بررسی مقدار None عه:
🐍 @python_rd
🔹توی پایتون، عملگر == مقدار دو متغیر رو مقایسه میکنه؛ اما is بررسی میکنه که آیا هر دو متغیر دقیقاً به یک آبجکت در حافظه اشاره میکنن یا نه.
numbers1 = [1, 2, 3]
numbers2 = [1, 2, 3]
numbers3 = numbers1
print(numbers1 == numbers2)
print(numbers1 is numbers2)
print(numbers1 is numbers3)
🔹 خروجی:
True
False
True
🔹 مقدار numbers1 و numbers2 یکسانه، پس نتیجهی == برابر True میشه؛ اما این دو لیست، آبجکتهای جداگانهای هستن، پس نتیجهی is برابر False میشه.
🔹برای مقایسهی معمولی مقادیر از == استفاده کن. کاربرد رایج و درست is، بررسی مقدار None عه:
if result is None:
print("مقداری وجود ندارد")
🐍 @python_rd
🔥4❤1
🔆 جستجوی سریعتر با ترفند Set
🔹 چرا پایتون وقتی لیستهات بزرگ میشن کند میشه؟ چون وقتی مینویسی if item in my_list پایتون مجبوره از اولِ لیست تا اون آیتم رو دونه دونه بگرده، حالا اگه لیستت بزرگ باشه، فاجعهست! برای اینکه این مشکل رو حل کنی، لیستت رو به set تبدیل کن. توی ستها، پایتون از مکانیزم Hash استفاده میکنه و عملاً در زمان صفر پیداش میکنه. اینطوری:
🔹 تفاوتش فقط توی همین آکولاد {} هست، اما سرعت اجرای کدت رو وحشتناک میبره بالا. این یعنی کدِ بهینهتر بدون درگیریهای پیچیده.
🐍 @python_rd
🔹 چرا پایتون وقتی لیستهات بزرگ میشن کند میشه؟ چون وقتی مینویسی if item in my_list پایتون مجبوره از اولِ لیست تا اون آیتم رو دونه دونه بگرده، حالا اگه لیستت بزرگ باشه، فاجعهست! برای اینکه این مشکل رو حل کنی، لیستت رو به set تبدیل کن. توی ستها، پایتون از مکانیزم Hash استفاده میکنه و عملاً در زمان صفر پیداش میکنه. اینطوری:
# کد کند (جستجوی خطی)
search_list = [1, 2, 3, 4, 5, ...]
if 500 in search_list: # کلی زمان میبره
pass
# کد سریع (جستجوی هشی)
search_set = {1, 2, 3, 4, 5, ...}
if 500 in search_set: # در یک لحظه پیدا میکنه
pass
🔹 تفاوتش فقط توی همین آکولاد {} هست، اما سرعت اجرای کدت رو وحشتناک میبره بالا. این یعنی کدِ بهینهتر بدون درگیریهای پیچیده.
🐍 @python_rd
🔥3
🔆 قاتل N+1 در کوئریهای جنگو
🔹 بزرگترین اشتباه توی جنگو، کوئری زدن داخل حلقهست. تصور کن ۱۰۰ تا پست داری و میخوای اسم نویسنده هرکدوم رو چاپ کنی. اگه بنویسی
🔹همین تغییر کوچک، تعداد کوئریها رو از ۱۰۰ تا به فقط ۱ دونه کاهش میده و سرعت لود صفحه رو توی جنگو به کل تغییر میده.
🐍 @python_rd
🔹 بزرگترین اشتباه توی جنگو، کوئری زدن داخل حلقهست. تصور کن ۱۰۰ تا پست داری و میخوای اسم نویسنده هرکدوم رو چاپ کنی. اگه بنویسی
posts = Post.objects.all() و بعد توی حلقه صداش بزنی، جنگو برای هر پست یه کوئری جداگانه به دیتابیس میفرسته! این یعنی ۱۰۰ تا کوئری اضافه و مرگِ سرعت سایت. راه حلش select_related هست که همه رو توی یک کوئریِ "JOIN" میاره. اینطوری مثال بزنیم:# کد بد (تعداد زیادی کوئری به دیتابیس)
posts = Post.objects.all()
for post in posts:
print(post.author.name)
# کد بهینه (فقط ۱ کوئری به دیتابیس)
posts = Post.objects.select_related('author').all()
for post in posts:
print(post.author.name)
🔹همین تغییر کوچک، تعداد کوئریها رو از ۱۰۰ تا به فقط ۱ دونه کاهش میده و سرعت لود صفحه رو توی جنگو به کل تغییر میده.
🐍 @python_rd
❤4🔥1