چند مورد از Best Practice های توسعه در جنگو به همراه جایزه

Django Best-practicesمطلب زیر جمع آوری نظرات کاربران کانال تلگرامی 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 ina single sentence of moderate length, or you need to say ‘and’ more than once, it probablymeans 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 ♾:ماژولار کردن Settings1- جدا کردن محیط توسعه از محیط پروداکشن۲- راحتی همکاری بین اعضای تیم هر کسی راحت می‌تونه تنظیمات خودش رو بزاره۳- تمیزی کداینم توضیح کاملش برای دوستان علاقه مندیه نکته هم بگم من خودم اوایل این کاررو نمی‌کردم ولی به مرور با مشکلات مختلفی که رو به رو شدم و راه های مختلفی که تست کردم به این رسیدم و هم خودم هم بقیه با این پترن راحت تر بودن خلاصه جایی ثبت نشده که حتما این کار رو کنیدبعضی ها پکیج دیکاپل اینوایرمنت ‌وریبل لینوکس و ... رو استفاده می‌کنن صرفا تجربیه۱- توی گیت ایگنور local.py و keys.pyرو بزارید۲- همونجایی که Settings.pyوجود داره یه پکیج به نام settings ایجاد کنید(دایرکتوری + init )۳- توی دایرکتوری که ایجاد کردید فایل های زیر رو بسازیدbase.pylocal.pykeys.pydev.pyprod.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 = &quotrandom gen hash&quot۹- فایل 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.rialModle.ethاما با این دو ویژگی که گفتم می تونید به شکل زیر هم انجامش دادcrypto = 'rial' Model.__getattribute__(crypto)این مورد خیلی به من کمک کرد و بلد نبودمشتشکر از توجه شما، در صورتی که نکته جدید به پست اضافه شد، اینجا اضافه اش میکنم