در حال یادگیری بهتر Django
چند مورد از Best Practice های توسعه در جنگو به همراه جایزه
مطلب زیر جمع آوری نظرات کاربران کانال تلگرامی Django Expert با آدرس https://t.me/djangoex هست.
یکی از ادمین های این کانال پستی به عنوان مسابقه در این لینک در کانال منتشر کرده و قراره جایزه هم بده.
با توجه به اینکه پاسخ ها به این مطلب از سمت افرادی هست که تجربه واقعی کار با فریمورک جنگو رو دارند، فکر کردم که بهتره پاسخ هارو با ذکر نام کاربر منتشر کنم، تا شاید برای دیگران هم مفید باشه.
من پاسخ ها به این پست رو منتشر می کنم (البته با یکم ویرایش) و هیچکدام از این موارد رو تایید و یا رد نمی کنم. اما کلیات مطلب رو مناسب دیدم و میتونه برای علاقمندان به جنگو مناسب باشه.
سوال: یکی از best-practiceهایی که در هنگام توسعه اپلیکیشن های django یاد گرفتید و استفاده کردید را توضیح دهید.
کاربر Farid:
یکی از بهترین پرکتیس هایی که یاد گرفتم اینه:
In DRF, it's better to have more views designed to be as atomic as possible than a few views with many options
در ادامه:
If a serializer is troublesome and is outrageously complex, why not break it up into two different serializers for the same model ?
از فواید این پرکتیس:
1) داکیومنتیشن راحت تر و سریعتره چون هر کامپوننت کار کمتری انجام میده
2) تست راحت تر
3) باتل نک ها یا گلوگاه ها راحتتر resolve میشن
4) امنیتش هم بالاتره چون دسترسی ها رو به ازای هر ویو تغییر میدیم ( به جای کنترل دسترسی از طریق کد نوشتن توی ویو )
کاربر Ali:
این متن از کتاب two scoops of django هستش که برای best practice خیلی کتاب خوبیه
In essence, each app should be tightly focused on its task. If an app can’t be explained in
a single sentence of moderate length, or you need to say ‘and’ more than once, it probably
means the app is too big and should be broken up.
کمکی که به من کرده اینه میتونم از اپی که ساختم توی پروژه های مختلف استفاده کنم.
کاربر Parsa:
"Fat Models, skinny views"
یکی از مفید ترین practice ها برای من بود که به جای اینکه یک سری logic رو در viewهامون تکرار کنیم، میایم و logic رو در modelها یا model manager ها قرار می دهیم.
که با این کار :
1- از اصل DRYپیروی می کنیم.
2- همچنین کد ما قابل تست کردن هست.
3- کد ما maintainableو extensible هست.
کاربر Yaser Rahimi:
فانکشنی که طولش بیشتر از یه صفحه بشه یجای کارش میلنگه
کاربرABB ♾:
ماژولار کردن Settings
1- جدا کردن محیط توسعه از محیط پروداکشن
۲- راحتی همکاری بین اعضای تیم هر کسی راحت میتونه تنظیمات خودش رو بزاره
۳- تمیزی کد
اینم توضیح کاملش برای دوستان علاقه مند
یه نکته هم بگم من خودم اوایل این کار
رو نمیکردم ولی به مرور با مشکلات مختلفی که رو به رو شدم و راه های مختلفی که تست کردم به این رسیدم و هم خودم هم بقیه با این پترن راحت تر بودن خلاصه جایی ثبت نشده که حتما این کار رو کنیدبعضی ها پکیج دیکاپل اینوایرمنت وریبل لینوکس و ... رو استفاده میکنن صرفا تجربیه
۱- توی گیت ایگنور local.py و keys.py
رو بزارید
۲- همونجایی که Settings.pyوجود داره یه پکیج به نام settings ایجاد کنید(دایرکتوری + init )
۳- توی دایرکتوری که ایجاد کردید فایل های زیر رو بسازید
base.py
local.py
keys.py
dev.py
prod.py
۴- هرچی توی settings.py دارید بریزید توی base.py و settings.pyرو پاک کنید
۵- dev.pyمحیط توسعه مون هست پی هر کانفیگی برای توسعه نیاز داریم میزاریم اینجا برای مثال
from .base import *
DEBUG = True
try:
from backend.settings.local import *
except Exception:
pass
INSTALLED_APPS += ['debug_toolbar', 'django_extensions']
MIDDLEWARE += [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
۶- فایل بعدی prod.pyهست که برای محیط پروداکشنمون هست مثلا میتونیم اینجا سنتری و ... رو اضافه کنیم
from .base import *
DEBUG = False
۷- بعدی local.py هست اینجا هرچیزی رو که میخوایم رو از base.py اورراید میکنیم مثلا اینجا پسورد دیتابیس خودمون رو میزاریم یا تنظیمات هاست رو تغییر میدیم مناسب با سیستم خودمون پوش هم نمیشه
۸- بعدی keys.pyاینجا کلید ها رو میزاریم حالا سنتری کاوه نگار زرین پال و...
برای فراخوانی هم
try:
from .keys import SENTRY_KEY
except Exception:
SENTRY_KEY = "random gen hash"
۹- فایل init
اینجا تعیین میکنیم تنظیمات چه محیطی اعمال شه
env_name = 'dev'
if env_name == 'prod':
from .prod import *
elif env_name == 'dev':
from .dev import *
کاربر Farid:
من ترجیح میدم برای مورد دوم که فرمودین از پکیج decouple استفاده کنم.
مورد دوم:
۲- همونجایی که Settings.pyوجود داره یه پکیج به نام settings ایجاد کنید(دایرکتوری + init )
کاربر Alireza:
خیلی خوبه فقط با keys یخورده موافق نیستم استفاده از .env رو ترجیح میدم (با decouple یا django-environ یا...)
اشاره به مورد دوم هست J
(در ادامه یکم بحث شده که سانسور کردم)
کاربرAmir Motahari:
من خودم شخصا:
۱. برای settingاز yaml استفاده میکنم، که دوتا نسخه داره، که یکیش قالب کلی + تنظیمات پیشفرض و دومی که در gitignoreهست، تنظیمات لوکال (هم روی سرور هم روی سیستم توسعه دهنده) و درصورت نیاز توسعه دهنده میتونه تنظیمات اختصاصی خودش رو اعمال کنه
۲. همیشه برای کوئری گرفتن از values استفاده میکنم که فقط فیلد های موردنظرم رو داشته باشم (۱.باعث بهبود میشه ۲. مشکل n+1پیش نمیاد)
۳. این رو هم جایی ننوشته ولی همیشه برای کوئری های گزارش(که اغلب فشار روی دیتابیس میاره، چون باید عملیات به نسبت سنگینی انجام بدن) چک میکنم که یک وقتی ormجنگو کار اضافه ای انجام نده و همیشه دربهترین حالت ممکن اینکار انجام بشه، برای اینکار میتونید از این روش:
Queryset.query.__str__()
۳. برای کارهای تکراری سعی میکنم از generic viewکاستوم شده خودم استفاده کنم(مثلا cbvبرای datatable با پیاده سازی قابلیت های اون مثل pagging، searchو...)
۴. توی روت پروژه برای متد/کلاس های کاربری سراسری یک دایرکتوری به اسم utility یا utilise ایجاد میکنم و این ابزار ها رو به تفکیک کاربردشو براشون فایل جداگانه ایجاد میکنم (مثلا در فایل date.pyتمام متد/کلاس های کابردی مربوط یه تاریخ و زمان رو قرار میدم)
۵. ویو ajaxها رو از ویو اصلی جدا میکنم (همینطور برای فرم ها)
۶. کامنت کامنت کامنت، همیشه برای کدهاتون کامنت گزاری کنید
اگر مورد جدیدی یادم بیاد، به همین اضافه میکنم
کاربر edoardo:
یکی از چیز هایی که برای من جالب اومد اینکه تونستم دیزاین پترن سینگلتون رو اجرا کنم توی مدلم و خب کسایی که با این پترن اشنایی دارن از مزایاش اگاهن خب اون موقع که من نوشتم نمیدونستم کلی مقاله براش هست
ولی اگه پروژه ای رو استارت زدین فک کنم خوبه که ازش استفاده کنید و منطق کلیش اینه نمیزاره از کلاستون بیشتر از یک instance ساخته بشه که روی پرفورمنس تاثیر داره
حالا بحثش یکم طولانیه ولی این لینک میتونه دید خوبی بهتون بده
https://steelkiwi.com/blog/practical-application-singleton-design-pattern/
و اگه حوصله پیاده سازی ندارین تو pypiبگردین
احتمالا براش پکیج نوشتن
بحث بعدی که شاید براتون جالب باشه بحث ستینگه که از فایل پایتون به ماژول تغییرش میدین و خب مزایایی که داره میتونین
تقسیم بندی کنین بخش های ستینگ رو وحتی براش .envهای مختلفی بسازین که تو دو حالت development و productionاستفاده کنید بشخصه برا من مفید بود وخب منبع براش ندارم واقعیتش ولی two scoop of django درموردش نوشته
و درمورد type hint هایی که تازه اومدن بخونین
Fastapiداره بشدت ازش استفاده میکنه
البته فک کنم از pydanticاستفاده میکنه و بر اساس اون ساخته شده ولی به شدت جالبه ?
و اخرین نکته که شاید به درد دوستان بخوره بحث کوئری زدنه خیلی نوشتم ولی این مقاله بهتون دید خوبی میده در مورد یه سری کوئری ها یی که فکر میکنم بهینه هستن ولی نیستن :)
https://link.medium.com/VdGpvVHxDgb
کاربر Fazel:
یکی از کاربردی ترین مواردی که می تونم بگم، که خیلی هم دنبالش گشته بودم، حتی تو این گروه هم چندین بار پرسیدم اما کسی پاسخگو نبود، استفاده از getattribute و setattr هست
به طوری من نمی تونستم کد هارو reusable بنویسم، اما با استفاده از این دو مورد نزدیک به چهار هزار خط کد رو تبدیل به سیصد خط کرد
فرض کنید یک مدل دارید که فیلد های rial, btc, eth, bch, usdt,... رو داره
برای دسترسی به این فیلدها باید بزنید
Model.rial
Modle.eth
اما با این دو ویژگی که گفتم می تونید به شکل زیر هم انجامش داد
crypto = 'rial'
Model.__getattribute__(crypto)
این مورد خیلی به من کمک کرد و بلد نبودمش
تشکر از توجه شما، در صورتی که نکته جدید به پست اضافه شد، اینجا اضافه اش میکنم
مطلبی دیگر از این انتشارات
بررسی مک بوک پرو 2015 در سال 2019!
مطلبی دیگر از این انتشارات
مثال ساده ای از Continuous Integration
مطلبی دیگر از این انتشارات
کاتلین یا جاوا ؟