Repository: ftg-iran/ddpabp-persian Branch: main Commit: 08b73c1e931e Files: 21 Total size: 426.4 KB Directory structure: gitextract_sifllnh9/ ├── .nojekyll ├── 01-Django-and-Patterns/ │ └── README.md ├── 02-ApplicationDesign/ │ └── README.md ├── 03-Models/ │ └── README.md ├── 04-Views-and-URLs/ │ └── README.md ├── 05-Templates/ │ └── README.md ├── 06-AdminInterface/ │ └── README.md ├── 07-Forms/ │ └── README.md ├── 08-WorkingAsynchronously/ │ └── README.md ├── 09-CreatingAPIs/ │ └── README.md ├── 10-Dealing-with-LegacyCode/ │ └── README.md ├── 11-Testing-and-Debugging/ │ └── README.md ├── 12-Security/ │ └── README.md ├── 13-Production-Ready/ │ └── README.md ├── Appendix-A-Python2-Versus-Python3/ │ └── README.md ├── CONTRIBUTING.md ├── README.md ├── _sidebar.md ├── custom.css ├── custom.js └── index.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .nojekyll ================================================ ================================================ FILE: 01-Django-and-Patterns/README.md ================================================ # جنگو الگوها در این فصل در مورد موضوعات زیر صحبت خواهیم کرد: * [چرا جنگو؟](#چرا-جنگو) * [داستان جنگو](#داستان-جنگو) * [جنگو چگونه کار می کند؟](#جنگو-چگونه-کار-می-کند) * [الگو چیست؟](#الگو-چیست) * [مجموعه های الگوهای شناخته شده](#گروه-چهار-الگو-gang-of-four-patterns) * [الگوها در جنگو](#الگوها-در-این-کتاب) بر اساس گزارش جهانی استارتاپ بووی گای، در سال 2013 بیش از 136000 شرکت اینترنتی در سراسر جهان وجود داشت که بیش از 60000 شرکت فقط در آمریکا وجود داشت. از این تعداد، 87 شرکت آمریکایی بیش از یک میلیارد دلار ارزش دارند. مطالعه دیگری می گوید که از 12000 نفر بین 18 تا 30 سال در 27 کشور، بیش از دو سوم فرصت هایی را برای کارآفرین شدن می بینند. این رونق کارآفرینی در استارت آپ های دیجیتال در درجه اول به دلیل ارزان شدن و فراگیر شدن ابزارها و فناوری های استارت آپ ها است. ایجاد یک برنامه وب کامل به لطف فریمورک های قدرتمند، زمان و مهارت بسیار کمتری نسبت به گذشته می طلبد. فیزیکدانان، مربیان، هنرمندان و بسیاری دیگر بدون پیشینه مهندسی نرم افزار در حال ایجاد برنامه های کاربردی مفیدی هستند که به طور قابل توجهی در حال پیشرفت حوزه خود هستند. با این حال، آنها ممکن است از اصول طراحی مهندسی نرم افزار مورد نیاز برای ساخت نرم افزار بزرگ و قابل نگهداری آگاه نباشند. مطالعه چهار پیادهسازی مختلف از یک برنامه کاربردی مبتنی بر وب در نروژ نشان داد که پیادهسازیهایی با بوهای کد شناخته شده و طرحهای ضد الگو مستقیماً با مشکلات نگهداری مرتبط هستند. نرم افزاری که طراحی ضعیفی دارد ممکن است به همان اندازه کار کند، اما انطباق با الزامات در حال تحول در دنیایی که به سرعت در حال تغییر است، دشوار است. مبتدی ها اغلب مشکلات طراحی را در اواخر پروژه خود کشف می کنند. به زودی، آنها سعی می کنند همان مشکلاتی را که دیگران با آن مواجه شده اند، حل کنند. اینجاست که درک الگوها واقعاً می تواند به صرفه جویی در وقت آنها کمک کند. ### چرا جنگو؟ هر برنامه وب متفاوت است، مانند یک تکه مبلمان دست ساز. به ندرت یک مبل تولید انبوه پیدا می کنید که تمام نیازهای شما را به خوبی برآورده کند. حتی اگر با یک نیاز اساسی مانند وبلاگ یا شبکه اجتماعی شروع کنید، نیازهای شما به آرامی افزایش مییابد و به راحتی میتوانید با بسیاری از محلولهای نیمهپخت که با چسب نواری روی محلولهای کاتر کوکیها چسبانده شدهاند، خاتمه دهید. به همین دلیل است که FrameWork های وب مانند جنگو یا ریل بسیار محبوب شده اند. FrameWorkها توسعه را سرعت میبخشند و بهترین روشها را در خود دارند. با این حال، آنها همچنین به اندازه کافی انعطافپذیر هستند تا به شما امکان دسترسی به لولهکشی کافی برای کار را بدهند. امروزه فریم ورک های وب در همه جا وجود دارند و اکثر زبان های برنامه نویسی حداقل یک فریم ورک انتها به انتها مشابه جنگو دارند. احتمالا پایتون نسبت به بسیاری از زبان های برنامه نویسی FrameWork های وب بیشتری دارد. نگاهی گذرا به فهرست بسته پایتون (PyPI) 13045 بسته شگفتانگیز مربوط به محیطهای وب را نشان میدهد. برای جنگو، مجموع 9091 بسته است. ویکی پایتون بیش از 54 FrameWork وب فعال را فهرست میکند که محبوبترین آنها جنگو، فلاسک، پیرامید و زوپ است. پایتون همچنین دارای تنوع گسترده ای در فریمورک ها است. فریم ورک میکرو وب بطری فشرده تنها یک فایل پایتون است که هیچ وابستگی ندارد و به طرز شگفت انگیزی قادر به ایجاد یک برنامه وب ساده است. علیرغم این گزینههای فراوان، جنگو با اختلاف زیادی به عنوان یک مورد علاقه بزرگ ظاهر شده است. Djangosites.org بیش از 5263 سایت نوشته شده در جنگو را فهرست می کند، از جمله داستان های موفقیت معروفی مانند اینستاگرام، پینترست، و Disqus. همانطور که توضیحات رسمی می گوید، جنگو (https://djangoproject.com) یک FrameWork وب سطح بالا پایتون است که توسعه سریع و طراحی تمیز و عملی را تشویق می کند. به عبارت دیگر، این یک FrameWork وب کامل با باتری هایی است که دقیقاً مانند پایتون در آن گنجانده شده است. رابط مدیریت خارج از جعبه، یکی از ویژگی های منحصر به فرد جنگو، برای ورود و مدیریت اولیه داده ها بسیار مفید است. مستندات جنگو به دلیل اینکه برای یک پروژه منبع باز بسیار خوب نوشته شده است مورد تحسین قرار گرفته است. در نهایت، جنگو در چندین وب سایت پر ترافیک آزمایش شده است. تمرکز فوقالعاده دقیقی بر امنیت با محافظت در برابر حملات رایج مانند اسکریپتهای متقاطع (XSS)، جعل درخواستهای متقابل سایت (CSRF) تا تهدیدات امنیتی در حال تکامل مانند الگوریتمهای هش رمز عبور ضعیف است اگرچه میتوانید از جنگو برای ساخت هر نوع برنامه وب در تئوری استفاده کنید، اما ممکن است برای هر موردی بهترین نباشد. به عنوان مثال، برای نمونه سازی اولیه یک وب سرویس ساده در یک سیستم تعبیه شده با محدودیت های حافظه فشرده، ممکن است بخواهید از Flask استفاده کنید، در حالی که ممکن است در نهایت به دلیل استحکام و ویژگی های آن به جنگو بروید. ابزار مناسب برای کار را انتخاب کنید. اگر به سایر FrameWork های وب عادت داشته باشید، برخی از ویژگی های داخلی، مانند رابط مدیر، ممکن است عجیب به نظر برسد. برای درک طراحی جنگو، بیایید دریابیم که چگونه به وجود آمد. ## داستان جنگو وقتی به اهرام مصر نگاه می کنید، فکر می کنید که چنین طراحی ساده و مینیمال باید کاملاً آشکار باشد. در حقیقت، آنها محصول 4000 سال تکامل معماری هستند. اهرام پله ای، طرح اولیه (و درهم و برهم)، دارای شش بلوک مستطیل شکل در حال کاهش بود. چندین بار اصلاحات معماری و مهندسی طول کشید تا اینکه سازههای آهکی مدرن، لعابدار و بادوام اختراع شدند. با نگاه کردن به جنگو، ممکن است احساس مشابهی داشته باشید - آنقدر زیبا ساخته شده است که باید بی عیب و نقص تصور شده باشد. برعکس، نتیجه بازنویسیها و تکرارهای سریع در یکی از پرفشارترین محیطهای قابل تصور بود - اتاق خبر! در پاییز 2003، دو برنامه نویس، *آدریان هولواتی* و *سایمون ویلیسون* که در روزنامه *لارنس ژورنال-ورلد* کار می کردند، مشغول ایجاد چندین وب سایت خبری محلی در کانزاس بودند. این سایتها، از جمله *LJWorld.com*، *Lawrence.com*، و *KUsports.com*، مانند بسیاری از سایتهای خبری، نه تنها درگاههای محتوا محور مملو از متن، عکس و ویدئو بودند، بلکه دائماً سعی میکردند نیازهای مردم را برآورده کنند. جامعه محلی لارنس با برنامههایی مانند فهرست راهنمای کسبوکار محلی، تقویم رویدادها و آگهیها. ### یک FrameWork متولد می شود البته این به معنای کار زیاد برای سایمون، آدریان و بعدها جاکوب کاپلان ماس بود که به تیم آنها پیوسته بودند. با مهلت های بسیار کوتاه، گاهی اوقات تنها با چند ساعت اطلاع رسانی. از آنجایی که اولین روزهای توسعه وب در پایتون بود، آنها مجبور بودند برنامه های وب را عمدتاً از ابتدا بنویسند. بنابراین، برای صرفه جویی در زمان گرانبها، آنها به تدریج ماژول ها و ابزارهای رایج را به چیزی به نام *CMS* تغییر دادند. در نهایت، بخشهای مدیریت محتوا به پروژهای جداگانه به نام Ellington CMS تبدیل شد که به یک محصول تجاری موفق CMS تبدیل شد. بقیه CMS یک FrameWork زیربنایی منظم بود که به اندازه کافی عمومی بود که برای ساخت برنامه های کاربردی وب از هر نوع استفاده شود. تا جولای 2005، این FrameWork توسعه وب به عنوان جنگو (تلفظ Jang-Oh) تحت مجوز منبع باز توزیع نرم افزار برکلی (BSD) منتشر شد. این نام از گیتاریست افسانه ای جاز جنگو راینهارت گرفته شد. و بقیه، همانطور که می گویند، تاریخ است. ### حذف جادو جنگو به دلیل خاستگاه فروتنانهاش به عنوان یک ابزار داخلی، دارای موارد عجیب و غریب مخصوص لارنس ژورنال جهان بود. برای اینکه جنگو واقعاً هدف کلی باشد، تلاشی با عنوان حذف لارنس قبلاً در حال انجام بود. با این حال، مهم ترین تلاش برای بازسازی که توسعه دهندگان جنگو باید انجام می دادند Removing the Magic نام داشت. این پروژه بلندپروازانه شامل پاکسازی تمام زگیلهایی بود که جنگو در طول سالها جمعآوری کرده بود، از جمله جادوی زیادی (یک اصطلاح غیررسمی برای ویژگیهای ضمنی) و جایگزینی آنها با کد پایتونیک طبیعیتر و صریحتر. برای مثال، کلاسهای مدل به جای اینکه مستقیماً از ماژول `models.py` که در آن تعریف شده بودند وارد شوند، از یک ماژول جادویی به نام `django.models.*` وارد میشدند. در آن زمان، جنگو حدود صد هزار خط کد داشت و بازنویسی قابل توجهی از API بود. در 1 می 2006، این تغییرات، تقریباً به اندازه یک کتاب کوچک، در تنه نسخه توسعهدهنده جنگو ادغام شدند و با نسخه 0.95 جنگو منتشر شدند. این یک گام مهم به سوی نقطه عطف جنگو 1.0 بود. ### جنگو مدام بهتر می شود هر ساله کنفرانس هایی به نام DjangoCons در سرتاسر جهان برای توسعه دهندگان جنگو برگزار می شود تا بتوانند با یکدیگر ملاقات کنند و با یکدیگر تعامل داشته باشند. آنها یک سنت شایان ستایش در ارائه یک سخنرانی نیمه طنز در مورد اینکه چرا جنگو بد است، دارند. این می تواند عضوی از جامعه جنگو یا شخصی باشد که روی FrameWork های وب رقیب کار می کند یا هر شخصیت برجسته ای باشد. در طول سالها، شگفتانگیز است که چگونه توسعهدهندگان جنگو این انتقادات را مثبت میگرفتند و در نسخههای بعدی آن را کاهش میدادند. در اینجا خلاصهای از پیشرفتهای مربوط به چیزی است که زمانی در جنگو یک کاستی بود و نسخهای که در آن برطرف شد: * کتابخانه جدید مدیریت فرم (Django 0.96) * جداسازی ادمین از مدل ها (Django 1.0) * پشتیبانی از چندین پایگاه داده (Django 1.2) * مدیریت بهتر فایل های استاتیک (Django 1.3) * پشتیبانی بهتر از منطقه زمانی (Django 1.4) * مدل کاربر قابل تنظیم (Django 1.5) * مدیریت بهتر تراکنش (جنگو 1.6) * انتقال پایگاه داده داخلی (جنگو 1.7) * موتورهای قالب چندگانه (جنگو 1.8) * نحو ساده شده مسیریابی URL (Django 2.0) با گذشت زمان، جنگو به یکی از اصطلاحی ترین پایگاه های کد پایتون در حوزه عمومی تبدیل شده است. کد منبع جنگو همچنین مکانی عالی برای یادگیری معماری یک FrameWork وب بزرگ پایتون است. ### جنگو چگونه کار می کند؟ برای درک واقعی جنگو، باید زیر کاپوت را نگاه کنید و قسمت های متحرک مختلف داخل آن را ببینید. این می تواند هم روشنگر و هم طاقت فرسا باشد. اگر قبلاً با اطلاعات زیر آشنا هستید، ممکن است بخواهید از این بخش صرفنظر کنید:  *نحوه پردازش درخواست های وب در یک برنامه معمولی جنگو* نمودار قبلی سفر ساده درخواست وب از مرورگر بازدیدکننده به برنامه جنگو و بازگشت را نشان می دهد. مسیرهای شماره گذاری شده به شرح زیر است: 1. مرورگر درخواست را (در اصل یک رشته بایت) به وب سرور شما ارسال می کند. 2. وب سرور شما (مثلاً Nginx) درخواست را به یک سرور رابط دروازه وب سرور (WSGI) (مثلا uWSGI) تحویل می دهد یا مستقیماً یک فایل (مثلاً یک فایل CSS) را از سیستم فایل ارائه می دهد. 3. برخلاف وب سرور، سرورهای WSGI می توانند برنامه های پایتون را اجرا کنند. این درخواست یک فرهنگ لغت پایتون به نام `environ` را پر می کند و به صورت اختیاری، از چندین لایه میان افزار عبور می کند و در نهایت به برنامه جنگو شما می رسد. 4. URLconf (پیکربندی URL) ماژول موجود در `urls.py` پروژه شما، یک نمای را برای رسیدگی به درخواست بر اساس URL درخواستی انتخاب می کند. درخواست به HttpRequest، یک شی پایتون تبدیل شده است. 5. نمای انتخاب شده معمولاً یک یا چند مورد از کارهای زیر را انجام می دهد: a. از طریق مدل ها با پایگاه داده صحبت می کند. b. HTML یا هر پاسخ فرمت شده دیگری را با استفاده از Template ارائه می دهد c. یک متن ساده را بر میگرداند ( نشان داده نمیشود) d. در صورت وجود، یک exception بر میگرداند 6. شیع `HttpResponse` به متن تبدیل (Render) میشود. 7. یک صفحه وب با رندر زیبا در مرورگر شما دیده می شود. اگرچه جزئیات خاصی حذف شده است، این نمایش باید به شما در درک معماری سطح بالای جنگو کمک کند. همچنین نقشهایی را که اجزای کلیدی بازی میکنند، مانند مدلها، نماها و قالبها نشان میدهد. بسیاری از اجزای جنگو بر اساس چندین الگوی طراحی شناخته شده هستند. ### الگو چیست؟ چه چیزی بین کلمات **نقشه** ، **داربست** و **نگهداری** مشترک است؟ این اصطلاحات توسعه نرم افزار از دنیای ساخت و ساز ساختمان و معماری به عاریت گرفته شده است. با این حال، یکی از تأثیرگذارترین اصطلاحات از رساله ای در معماری و شهرسازی می آید که در سال 1977 توسط معمار برجسته اتریشی کریستوفر الکساندر و تیمش متشکل از موری سیلورستاین، سارا ایشیکاوا و چندین نفر دیگر نوشته شده است. اصطلاح الگو پس از کار اصلی آنها، *A Pattern Language: Towns, Buildings, Construction* (جلد 2 در یک مجموعه پنج کتابی)، بر اساس بینش شگفت انگیزی که کاربران در مورد ساختمان های خود بیش از هر معمار دیگری می دانند، رایج شد. یک الگو به یک مشکل روزمره و راه حل پیشنهادی اما آزمایش شده آن اشاره دارد. کریستوفر الکساندر در این کتاب چنین می گوید:
"هر الگو یک مشکل را توصیف می کند که بارها و بارها در محیط ما رخ می دهد و سپس هسته راه حل آن مشکل را به گونه ای توصیف می کند که می توانید از این راه حل میلیون ها بار استفاده کنید، بدون اینکه هرگز آن را به همان روش انجام دهید. دو برابر."
برای مثال، الگوی *بالهای نوری* او توضیح میدهد که چگونه مردم ساختمانهایی با نور طبیعیتر را ترجیح میدهند و پیشنهاد میکند که ساختمان را به گونهای تنظیم کنید که از بال تشکیل شده باشد. این بال ها باید بلند و باریک باشند و هرگز بیش از 25 فوت عرض نداشته باشند. دفعه بعد که از قدم زدن در راهروهای طولانی یک دانشگاه قدیمی لذت بردید، از این الگو سپاسگزار باشید. کتاب آنها شامل 253 الگوی عملی از این قبیل بود، از طراحی یک اتاق گرفته تا طراحی کل شهر. مهمتر از همه، هر یک از این الگوها نامی برای یک مسئله انتزاعی گذاشتند و با هم یک *زبان الگو* را تشکیل دادند. به یاد دارید که اولین بار با کلمه déjà vu برخورد کردید؟ احتمالاً فکر کرده اید: "وای، من هرگز نمی دانستم که کلمه ای برای آن تجربه وجود دارد." به طور مشابه، معماران نه تنها قادر به شناسایی الگوها در محیط خود بودند، بلکه میتوانستند در نهایت آنها را به گونهای نامگذاری کنند که همتایان خود بتوانند آن را درک کنند. در دنیای نرم افزار، اصطلاح الگوی طراحی به یک راه حل کلی قابل تکرار برای یک مشکل رایج در طراحی نرم افزار اشاره دارد. این رسمی سازی بهترین شیوه هایی است که یک توسعه دهنده می تواند از آن استفاده کند. مانند دنیای معماری، زبان الگو ثابت کرده است که برای برقراری ارتباط روش خاصی برای حل یک مشکل طراحی با برنامه نویسان دیگر بسیار مفید است. مجموعه های مختلفی از الگوهای طراحی وجود دارد، اما برخی از آنها به طور قابل توجهی تاثیرگذارتر از بقیه بوده اند. #### گروه چهار الگو (Gang of four patterns) یکی از اولین تلاشها برای مطالعه و مستندسازی الگوهای طراحی، کتابی با عنوان *الگوهای طراحی: عناصر نرمافزار شی گرا قابل استفاده مجدد (Design Patterns: Elements of Reusable Object-Oriented Software) * توسط *اریش گاما*، *ریچارد هلم*، *رالف جانسون* و *جان ولیسیدز* بود که بعدها به گروه چهار نفر ( **Gang of Four «GoF»** ) معروف شد. ). این کتاب به قدری تأثیرگذار است که بسیاری 23 الگوی طراحی موجود در کتاب را برای خود مهندسی نرم افزار اساسی می دانند. در واقع، الگوها عمدتاً برای زبانهای برنامهنویسی شی گرا ثابت نوشته شدهاند و نمونههایی از کد در C++ و Smalltalk داشتند. همانطور که به زودی خواهیم دید، برخی از این الگوها ممکن است حتی در سایر زبان های برنامه نویسی با انتزاعات بالاتر مانند پایتون مورد نیاز نباشند. 23 الگو به طور کلی بر اساس نوع خود به شرح زیر طبقه بندی شده اند: * **الگوهای خلاقانه**: این الگوها شامل کارخانه انتزاعی، الگوی سازنده، روش کارخانه، الگوی نمونه اولیه و الگوی تکتنه است. * **الگوهای ساختاری**: اینها شامل الگوی آداپتور، الگوی پل، الگوی ترکیبی، الگوی تزئینی، الگوی نما، الگوی وزن پرواز و الگوی پروکسی است. * **الگوهای رفتاری**: این الگوها شامل زنجیره مسئولیت، الگوی فرمان، الگوی مفسر، الگوی تکرارکننده، الگوی میانجی، الگوی یادگاری، الگوی مشاهده گر، الگوی حالت، الگوی استراتژی، الگوی الگو، و الگوی بازدیدکننده است. در حالی که توضیح دقیق هر الگو خارج از محدوده این کتاب است، شناسایی برخی از این الگوهای موجود در خود پیادهسازی جنگو جالب خواهد بود: | **الگوی GoF** | **کامپوننت جنگو** | **توضیح** | الگوی فرمان | HttpRequest | این یک درخواست در یک شی | | الگوی مشاهده گر | سیگنال ها | هنگامی که یک شی تغییر حالت می دهد، همه شنوندگان آن به طور خودکار مطلع و به روز می شوند | | روش قالب | نماهای عمومی مبتنی بر کلاس | مراحل یک الگوریتم را می توان با زیر طبقه بندی بدون تغییر ساختار الگوریتم دوباره تعریف کرد | در حالی که این الگوها بیشتر مورد توجه کسانی است که درونیات جنگو را مطالعه می کنند، رایج ترین سؤالی که پرسیده می شود این است که خود جنگو تحت کدام الگو طبقه بندی می شود؟ #### آیا جنگو MVC است؟ **مدل-ویو-کنترلر (MVC)** یک الگوی معماری است که توسط Xerox PARC در دهه 70 اختراع شد. به عنوان چارچوبی که برای ساخت رابط های کاربری در Smalltalk استفاده می شود، در کتاب GoF در ابتدا به آن اشاره شد. امروزه MVC یک الگوی بسیار محبوب در فریمورک های برنامه های وب است. یک نوع سوال رایج این است که آیا جنگو یک چارچوب MVC است یا خیر پاسخ هم بله و نه است. الگوی MVC از جداسازی لایه ارائه از منطق برنامه حمایت می کند. به عنوان مثال، هنگام طراحی یک API وب سایت بازی آنلاین، ممکن است جدول امتیازات بالای یک بازی را به عنوان یک فایل HTML، XML یا **مقادیر جدا شده با کاما (CSV)** ارائه دهید. با این حال، کلاس مدل زیربنایی آن مستقل از نحوه ارائه نهایی داده ها طراحی می شود. MVC در مورد کاری که مدل ها، نماها و کنترلرها انجام می دهند بسیار سخت است. با این حال، جنگو نگاه بسیار کاربردی تری به برنامه های کاربردی وب دارد. با توجه به ماهیت پروتکل HTTP، هر درخواست برای یک صفحه وب مستقل از هر درخواست دیگری است. چارچوب جنگو مانند یک خط لوله برای پردازش هر درخواست و آماده سازی پاسخ طراحی شده است. جنگو این را معماری **مدل-تمپلیت-ویو (MTV)** می نامد. نگرانیها بین کلاسهای واسط پایگاه داده (مدل)، کلاسهای پردازش درخواست (نما) و زبان قالب برای ارائه نهایی (الگو) جدایی وجود دارد. اگر این را با MVC کلاسیک مقایسه کنید، یک مدل با مدل های جنگو قابل مقایسه است. یک view معمولاً Templates جنگو است و کنترلر خود چارچوبی است که یک درخواست HTTP ورودی را پردازش می کند و آن را به تابع view صحیح هدایت می کند. اگر این به اندازه کافی شما را گیج نکرده است، جنگو ترجیح میدهد که تابع callback را برای مدیریت هر URL یک تابع view نامگذاری کند. این، متأسفانه، به ایده الگوی MVC از دیدگاه مربوط نمی شود. #### الگوهای فاولر (Fowler's) در سال 2002، مارتین فاولر **الگوهای معماری برنامه های سازمانی** را نوشت که حدود 40 الگوی را توصیف کرد که او اغلب در هنگام ساخت برنامه های سازمانی با آنها مواجه می شد. برخلاف کتاب GoF که الگوهای طراحی را توصیف می کرد، کتاب فاولر در مورد الگوهای معماری بود. از این رو، آنها الگوها را در سطح بسیار بالاتری از انتزاع توصیف می کنند و تا حد زیادی زبان برنامه نویسی آگنوستیک هستند. الگوهای فاولر به صورت زیر سازماندهی می شوند: * **الگوهای منطقی دامنه:** این الگوها شامل مدل دامنه، اسکریپت تراکنش، لایه سرویس و ماژول جدول است * **الگوهای معماری منبع داده:** اینها شامل دروازه داده ردیف، دروازه داده جدول، نگاشت داده و رکورد فعال است. * **الگوهای رفتاری شی-رابطه ای:** این الگوها شامل نقشه هویت، واحد کار و بار تنبل است. * **الگوهای ساختاری شی-رابطه ای:** این الگوها عبارتند از نگاشت کلید خارجی، نگاشت، نگاشت وابسته، نگاشت جدول انجمن، فیلد هویت، LOB سریال، ارزش جاسازی شده، نگاشتهای ارثی، ارث بری جدول تک، ارث بری جدول بتن، و ارث بری جدول کلاس. * **الگوهای نگاشت ابرداده شی رابطه ای:** این الگوها عبارتند از Query Object، Metadata Mapping و Repository. * **الگوهای ارائه وب:** اینها عبارتند از کنترل کننده صفحه، کنترلر جلو، کنترلر نمای مدل، نمای تبدیل، نمای الگو، کنترل کننده برنامه، و نمای دو مرحله ای * **الگوهای توزیع:** اینها شامل شی انتقال داده و نما از راه دور است * **الگوهای همزمانی آفلاین:** این الگوهای شامل قفل درشت دانه، قفل ضمنی، قفل آفلاین خوش بینانه و قفل آفلاین بدبینانه است. * **الگوهای وضعیت جلسه:** اینها شامل وضعیت جلسه پایگاه داده، وضعیت جلسه مشتری و وضعیت جلسه سرور است. * **الگوهای پایه:** این الگوها عبارتند از Mapper، Gateway، Layer Supertype، Registry، Value Object، Separated Interface، Money، Plugin، Case Special، Service Stub و Record Set. دانستن تقریباً همه این الگوها هنگام طراحی یک برنامه جنگو مفید است. در واقع، وبسایت فاولر به آدرس `http://martinfowler.com/eaaCatalog` یک کاتالوگ عالی از این الگوها به صورت آنلاین دارد. من به شدت توصیه می کنم آنها را بررسی کنید. جنگو تعدادی از این الگوها را نیز پیاده سازی می کند. جدول زیر تعدادی از آنها را فهرست می کنددانستن تقریباً همه این الگوها هنگام طراحی یک برنامه جنگو مفید است. در واقع، وبسایت فاولر به آدرس `http://martinfowler.com/eaaCatalog` یک کاتالوگ عالی از این الگوها به صورت آنلاین دارد. من به شدت توصیه می کنم آنها را بررسی کنید. جنگو تعدادی از این الگوها را نیز پیاده سازی می کند. جدول زیر تعدادی از آنها را فهرست می کند: | **الگوهای فاولر** | **کامپوننت های جنگو** | **توضیح** |:---------------------------:|:-------------------------:|:-----------------------------------------------------------------:| | رکورد فعال | مدل های جنگو | دسترسی به پایگاه داده را کپسوله کنید و منطق دامنه را روی آن داده ها اضافه کنید | | وراثت جدول کلاس | وراثت مدل ها | هر موجودیت در سلسله مراتب به یک جدول جداگانه نگاشت می شود | | فیلد هویت | ID فیلد | برای حفظ هویت، یک فیلد ID پایگاه داده را در یک شی ذخیره می کند | |Template view | قالب های جنگو | رندر خروجی HTML بوسلیه تبدیل علامت ها و حروف | #### آیا الگوهای بیشتری وجود دارد؟ بله حتما. الگوها همیشه کشف می شوند. مانند موجودات زنده، برخی جهش می یابند و الگوهای جدیدی را تشکیل می دهند، به عنوان مثال، انواع MVC مانند Model-view-presenter (MVP)، **Hierarchical model-view-controller (HMVC)** ، یا **Model View ViewModel (MVVM)**. الگوها نیز با گذشت زمان تکامل می یابند، زیرا راه حل های بهتری برای مشکلات شناخته شده شناسایی می شود. به عنوان مثال، الگوی Singleton زمانی به عنوان یک الگوی طراحی در نظر گرفته می شد، اما اکنون به دلیل حالت مشترکی که معرفی می کند، مشابه با استفاده از متغیرهای سراسری، به عنوان یک ضد الگو در نظر گرفته می شود. یک ضد الگو را می توان به عنوان راه حلی که معمولاً دوباره اختراع می شود، اما راه حلی بد برای یک مشکل تعریف کرد. برخی از کتابهای معروف دیگر که الگوهای فهرستنویسی دارند، معماری نرمافزار الگو محور (POSA) توسط Buschmann، Meunier، Rohnert، Sommerlad و Sta هستند. الگوهای ادغام سازمانی توسط هوپ و وولف. و طراحی سایت ها: الگوها، اصول و فرآیندها برای ایجاد یک تجربه وب مشتری محور توسط Duyne، Landay و Hong. ### الگوها در این کتاب این کتاب الگوهای طراحی و معماری خاص جنگو را پوشش میدهد که برای توسعهدهنده جنگو مفید است. هر الگو به این صورت ارائه خواهد شد: **نام الگو عنوان نام الگو است. اگر یک الگوی شناخته شده باشد، از نام رایج استفاده می شود. در غیر این صورت، نام مختصر و خود توصیفی انتخاب شده است. نام ها مهم هستند، زیرا به ساخت واژگان الگو کمک می کنند. تمام الگوها دارای قسمت های زیر خواهند بود: * مشکل: در اینجا به طور خلاصه به مشکل اشاره می شود * راه حل: این راه حل(های) پیشنهادی را خلاصه می کند * جزئیات مشکل: این موضوع زمینه مشکل را توضیح می دهد و احتمالاً مثالی را ارائه می دهد * جزئیات راه حل: این راه حل (ها) را به طور کلی توضیح می دهد و نمونه ای از اجرای جنگو را ارائه می دهد #### نقد الگوها علیرغم کاربرد تقریباً جهانی آنها، الگوها نیز سهم خود را از انتقاد دارند. رایج ترین استدلال ها علیه آنها به شرح زیر است: * **الگوها ویژگیهای زبان از دست رفته را جبران میکنند:** پیتر نورویگ دریافت که 16 الگو از 23 الگو در الگوهای طراحی در زبانهای پویا مانند Lisp یا Python نامرئی یا سادهتر هستند. برای مثال، از آنجایی که توابع قبلاً در پایتون اشیاء هستند، ایجاد کلاسهای جداگانه برای پیادهسازی الگوهای استراتژی غیرضروری است. * **الگوها بهترین شیوهها را تکرار میکنند:** بسیاری از الگوها اساساً رسمیسازی بهترین شیوهها، مانند تفکیک نگرانیها هستند، و ممکن است زائد به نظر برسند. الگوها می توانند منجر به مهندسی بیش از حد شوند: پیاده سازی الگو ممکن است در مقایسه با راه حل ساده تر کارآمدتر و بیش از حد باشد. * **الگوها می توانند منجر به مهندسی بیش از حد شوند:** پیاده سازی الگو ممکن است در مقایسه با راه حل ساده تر کارآمدتر و بیش از حد باشد. #### نحوه استفاده از الگوها اگرچه برخی از انتقادات قبلی کاملاً معتبر است، اما بر اساس نحوه استفاده نادرست از الگوها است. در اینجا چند توصیه وجود دارد که می تواند به شما در درک بهترین روش استفاده از الگوهای طراحی کمک کند: * بهتر است از الگوها برای بیان اینکه شما از یک رویکرد طراحی کاملاً درک شده پیروی می کنید استفاده می شود * اگر زبان شما از راه حل مستقیم پشتیبانی می کند، الگو را پیاده سازی نکنید * سعی نکنید همه چیز را از نظر الگوها بازسازی کنید * از یک الگو فقط در صورتی استفاده کنید که ظریف ترین راه حل در زمینه شما باشد * از ایجاد الگوهای جدید نترسید #### فلسفه طراحی پایتون ذن و جنگو به طور کلی، جامعه پایتون از اصطلاح *پایتونیک* برای توصیف یک کد اصطلاحی استفاده می کند. معمولاً به اصولی اشاره دارد که در *The Zen of Python* بیان شده است. که مانند یک شعر نوشته شده است، توصیف چنین مفهوم مبهمی بسیار مفید است. ** نکته: برای مشاهده *Zen of Python* سعی کنید این را در یک اعلان پایتون `وارد کنید`. علاوه بر این، توسعهدهندگان جنگو فلسفههای طراحی خود را در حین طراحی چارچوب در `https://docs.djangoproject.com/en/dev/misc/design-philosophies/` به طور واضح مستند کردهاند. در حالی که این سند فرآیند فکری پشت چگونگی طراحی جنگو را توضیح میدهد، اما برای توسعهدهندگانی که از جنگو برای ساخت برنامهها استفاده میکنند نیز مفید است. برخی از اصول مانند: **Don't Repeat Yourself (DRY)**, **loose coupling**, and **tight cohesion** می توانند به شما کمک کنند تا برنامه های جنگو قابل نگهداری و اصطلاحی بیشتری بنویسید. بهترین شیوه های جنگو یا پایتون پیشنهاد شده توسط این کتاب به روش زیر قالب بندی می شوند: ** نکته: از `BASE_DIR` در `settings.py` استفاده کنید و از کدگذاری نام دایرکتوری ها خودداری کنید. ### خلاصه در این فصل، ما به این موضوع پرداختیم که چرا مردم جنگو را نسبت به سایر چارچوب های وب، تاریخچه جالب آن و نحوه کارکرد آن انتخاب می کنند. ما همچنین الگوهای طراحی، مجموعه های الگوهای محبوب و بهترین شیوه ها را بررسی کردیم. در فصل بعد، نگاهی به چند مرحله اولیه در آغاز پروژه جنگو خواهیم داشت، مانند جمع آوری نیازمندی ها، ساخت ماکت ها و راه اندازی پروژه. ================================================ FILE: 02-ApplicationDesign/README.md ================================================ # طراحی برنامه در این بخش، موضوعات زیر را پوشش میدهیم: - جمعآوری نیازمندیها - ساخت یک سند کانسپت - ماکتهای HTML - چگونه یک پروژه را به اپهای مختلف تقسیم کنیم - آیا یک اپ جدید بنویسیم یا یک اپ موجود را بازنویسی کنیم - بهینهترین روشها قبل از شروع یک پروژه - چرا پایتون ۳ - کدام نسخه جنگو را استفاده کنیم - شروع پروژه SuperBook بسیاری از توسعهدهندگان یک پروژه جدید را با نوشتن کد آغاز میکنند. معمولاً چنین روشی به برداشتهای غلط، امکانات بیاستفاده و اتلاف زمان منتهی میشود. صرف وقت برای فهمیدن نیازهای اصلی مشتری، حتی در یک پروژه کوچک از نظر زمانی، میتواند نتایج باورنکردنی داشته باشد. مدیریت نیازمندیها یک مهارت کلیدی است که ارزش یادگیری دارد. ## چگونه نیازمندیها را جمعآوری کنیم؟ _"خلاقیت، بله گفتن به هر چیزی نیست، بلکه نه گفتن به هرچیزی غیر از ویژگیهای بسیار مهم است."_ _–استیو جابز_ من پروژههای محکوم به شکست بسیاری را فقط با گوش کردن دقیق به نیازهای مشتری و تعیین انتظارات درست، نجات دادهام. تنها سلاح من قلم وکاغذ (یا معادل دیجیتال آن) بوده است. فرآیند به طرز باورنکردنی ساده اما تأثیرگذار است. در اینجا چند نکته کلیدی آمده است تا در زمان جمعآوری نیازمندیها به یاد داشته باشید: 1. مستقیماً با صاحبان برنامه صحبت کنید حتی اگر از نظر فنی توانایی نداشته باشند. 2. اطمینان پیدا کنید که کاملاً نیازهای آنها را شنیدهاید و یادداشت برداشتهاید. 3. از اصطلاحات تخصصی مانند _models_ استفاده نکنید. ساده صحبت کنید و از اصطلاحات آشنا برای کاربر مانند _پروفایل کاربری_ استفاده کنید. 4. انتظارات درست ایجاد کنید. اگر چیزی از نظر فنی سخت یا غیرممکن است، مطمئن شوید که درست به مشتری توضیح دادهاید. 5. تا میتوانید طراحی کنید. افراد به طور طبیعی با تصویر راحتتر هستند، وبسایتها هم تصویری هستند. از خطوط ساده و چسباندن عکس استفاده کنید. لازم نیست همه چیز عالی باشد. 6. فرآیندهایی مانند ثبتنام را به بخشهای کوچک تقسیم کنید. هر عملکرد چند مرحلهای، باید در مستطیلهایی که با خط و فلش به هم وصل شدهاند رسم شود. 7. حالا، ویژگیهای مورد نیاز برنامه را به صورتی لیستی از سناریوهای کاربری و در شکلی ساده و قابل خواندن جمعآوری کنید. 8. سعی کنید نقش مؤثری در تقسیم ویژگیها به سه اولویت بالا، متوسط و پایین، ایفا کنید. 9. در قبول ویژگی جدید بسیار، بسیار محافظهکارانه برخورد کنید. 10. بعد از جلسه، یادداشتهای خود را با بقیه به اشتراک بگذارید تا از سوءتفاهم جلوگیری شود. جلسه اول طولانی خواهد بود (شاید یک کارگاه یک روزه یا یک جلسه چند ساعته). بعداً وقتی این جلسات تکرار شد میتوانید آنها را تبدیل به جلساتی نیم ساعته یا یک ساعته کنید. نتایج این جلسات احتمالاً یک صفحه نوشته و چند صفحه طراحی ضعیف خواهد بود. بعضیها یک _wireframe_ که اسکلت اصلی وبسایت است نیز میسازند. در این کتاب ما یک پروژه به نام SuperBook که یک شبکه اجتماعی برای ابرقهرمانان است میسازیم. یک وایرفریم ساده بر اساس صحبتهای ما با چندین ابرقهرمان که به صورت اتفاقی انتخاب شدهاند در اینجا آمده است:  *یک وایرفریم از وبسایت سوپربوک به صورت ریسپانسیو - صفحه بندی دسکتاپ و موبایل* ## آیا شما یک قصهگو هستید؟ خب، خلاصه یک صفحهای چیست؟ یک سند ساده است که شرح میدهد استفاده از سایت چه حسی دارد. تقریباً در تمام پروژههایی که من با آنها کار کردهام وقتی فرد جدید وارد تیم میشود، اگر از آنها خواسته شود که تمام اسناد را مطالعه کنند سریعاً دلسرد میشوند اما اگر قرار باشد فقط یک صفحه را مطالعه کنند تا بفهمند که هدف سایت چیست بسیار هیجانزده میشوند. شما میتوانید به سند هر نامی که دوست دارید بدهید؛ سند کانسپت، سند نیازمندیهای بازار، مستندات تجربه مشتری یا Epic Fragile StoryLog™ (در انتظار ثبت برند). واقعاً اهمیت خاصی ندارد. این سند باید بر روی تجربه کاربر متمرکز باشد تا جزییات فنی یا نحوه پیادهسازی. این سند باید کوتاه و جذاب برای مطالعه کردن باشد. در واقع قانون شماره یک جوئل اسپاسکی برای سند نیازمندیها _بامزهبودن_ است. اگر امکان دارد در مورد یک کاربر معمولی ( که در زبان بازاریابی پرسونا میگویند) بنویسید، مشکلاتی که آنها مواجه میشوند و روشی که وب اپلیکیشن مشکل آنها را برطرف میکند. تصور کنید که آنها چطور تجربه خود را برای دیگران شرح خواهند داد. سعی کنید این تصویر را بهدست آورید. اینجا یک سند کانسپت برای پروژه سوپربوک داریم: **_کانسپت سوپربوک_** _این مصاحبه پس از راهاندازی وبسایت ما سوپربوک، در آینده انجام شده است. یک تست کاربری ۳۰ دقیقهای دقیقاً قبل از مصاحبه اجرا شده است._ **_لطفا خودتان را معرفی کنید_** _ اسم من اَکسل است. من یک سنجاب خاکستری هستم که در مرکز نیویورک زندگی میکنم. همه من را اَکورن صدا میکنند.پدرم تی. بری که هنرمند شناختهشده هیپ هاپ بود من را به این نام صدا میکرد. فکر میکنم هیچ وقت اینقدر خوب نمیخواندم که کسب و کار خانوداگی را ادامه دهم. در واقع در ابتدا کمی عشق سرقت بودم. میدانید که، من به فندق و مانند آن حساسیت دارم اما بقیه رفیقهایم راحت میخورند. آنها میتوانند به سادگی در هر پارکی زندگی کنند. من مجبورم خلاق باشم، کافهها، سالنهای سینما یا پارکهای سرگرمی. من برچسبها را به دقت می خوانم._ ***خب اکورن فکر میکنی که چرا برای تست کاربری انتخاب شدهای؟*** _احتمالاً برای اینکه در برنامه ویژه NY Star که در مورد ابرقهرمانان کمتر شناخته شدهبود شرکت کردم. به نظرم این برای مردم جالب بود که یک سنجاب میتواند از مکبوک استفاده کند (مصاحبه کننده: این مصاحبه از طریق چت انجام شده است). علاوه بر این، من دقت نظر یک سنجاب را دارم._  ***بر اساس چیزی که دیدهاید نظر شما در مورد سوپربوک چیست؟*** _فکر میکنم که ایده فوقالعادهای است. منظورم این است که مردم معمولاً ابرقهرمانان را میبینند، با اینحال کسی به آنها توجهی ندارد. اکثر آنها تنها و غیر اجتماعی هستند. سوپربوک میتواند این وضعیت را تغییر دهد._ **_فکر میکنید که چه چیزی در سوپربوک متفاوت است؟_** _این سایت از ابتدا برای افرادی مانند ما ساخته شده است. منظورم این است که وقتی قرار است از هویت مخفی خود استفاده کنید مجبور نیستید موارد بیمعنی مانند "سابقه کار و تحصیلات" را پر کنید. اگرچه که من چنین چیزی ندارم ولی میتوانم بفهمم که چرا ممکن است یکی بخواهد این کار را بکند._ **_ممکن است به طور خلاصه برخی ویژگیهایی را که برای شما مهم بودند نام ببرید؟_** _بله حتماً، فکر میکنم این یک شبکه اجتماعی مناسب است که شما میتوانید:_ - _میتوان با هر نوع نام کاربری ثبت نام کرد (دیگر عبارت احمقانه "نام واقعی خود را وارد کنید" را نمیبینیم)_ - _طرفدارها میتوانندافراد را دنبال کنند بدون آنکه مجبور باشند آنها را به عنوان "دوست" اضافه کنند_ - _میتوان پست و کامنت ایجاد کرد و آنها را بازنشر کرد_ - _میتوان یک پست خصوصی را برای دیگری ارسال کرد_ \* همه چیز ساده است. لازم نیست ابرقهرمان باشید تا با آن کار کنید. **آکورن، از وقتی که گذاشتی تشکر میکنیم. \*** ## ماکتهای HTML در ابتدای ساخت وب اپلیکیشنها، ابزارهایی مانند فوتوشاپ و Flash به طور گستردهای استفاده میشدند تا ماکتهایی با کیفیت پیکسلی، ساخته شوند. الان به ندرت پیشنهاد میشوند یا مورد استفاده قرار میگیرند. امروزه ارائه یک تجربه یکسان بین موبایل، تبلت، لپ تاپ و سایر پلتفرمها بسیار مهمتر از یک طراحی پیکسلی بسیار دقیق است. در واقع، اکثر طراحان وب مستقیماً صفحهبندی خود را به صورت HTML انجام میدهند. ساختن یک ماکت HTML بسیار سریعتر و سادهتر از قبل است. اگر طراح وب شما در دسترس نیست، توسعهدهندگان میتوانند از یک فریمورک CSS مانند Bootsrap یا ZURB Foundation برای ساخت یک ماکت مناسب و زیبا استفاده کنند. هدف از ساخت یک ماکت، ایجاد پیشنمایشی واقعی از وبسایت است. ماکت نباید بر جزییات متمرکز باشد بلکه باید به نسبت طراحیهای خطی اولیه، به محصول نهایی نزدیکتر باشد و علاوه بر این تعاملی باشد. HTML ایستای خود را با اضافه کردن لینک و برخی تکه کدهای جاواسکریپتی ساده، پویاتر کنید. یک ماکت خوب میتواند تا ۸۰ درصد از تجربه کاربری نهایی را تنها با حدود ۱۰ درصد از توسعه اصلی، ایجاد کند. ## طراحی اپلیکیشن وقتی که شما تصویر خوبی از آنچه لازم است بسازید، پیدا کردید، وقت آن است که به پیادهسازی آن در جنگو فکر کنید. الان شروع کدنویسی وسوسهانگیز است، با اینحال اگر چند دقیقهای برای طراحی وقت بگذارید راههای بسیار متفاوتی برای حل مشکلات طراحی پیدا خواهید کرد. هنچنین شما میتوانید ابتدا تستها را طراحی کنید، همانطور که در متد **توسعه تست محور** (**Test-Driven Development**)، مطرح میشود. ما رویکرد TDD را در بخش ۱۱ _تست کردن و رفع مشکل_ بیشتر بررسی خواهیم کرد. هر رویکردی را که انتخاب کنید، خوب است که کمی توقف کنید و به این موضوعات فکر کنید: - راههای مختلف من برای پیادهسازی این اپلیکیشن چیست؟ - مزایا و معایب آن چیست؟ - در زمینه کار ما کدام فاکتورها مهمتر هستند؟ - در نهایت، کدام رویکرد بهترین است؟ بهترین طراحیها اغلب در مجموع ظریف و هماهنگ هستند.اینجاست که معمولاً الگوهای طراحی به شما کمک میکنند. کدهای خوب طراحی شده لزوماً برای خواندن، ساده نیستند اما برای توسعه و بهبود دادن سادهتر هستند. توسعهدهندگان باتجربه جنگو، به کلیت پروژه از روشهای مختلفی نگاه میکنند. این توسعهدهندگان با وفاداری به اصول DRY (شاید به خاطر اینکه تنبل شدهاند)، همواره فکر میکنند آیا من این عملکرد را قبلاً دیدهام؟ مثلاً آیا این لاگین به کمک سوشیال را میتوان به کمک یک پکیج کمکی مانند django-all-auth، پیادهسازی کرد؟ اگر مجبور باشند که اپ را خودشان بنویسند، به امید پیدا کردن بهترین طراحی، به انواع الگوهای طراحی فکر میکنند. با اینحال، در ابتدا نیاز است که یک پروژه را به اپهای کوچک تقسیم کنند. **تقسیم کردن پروژه به اپها** اپلیکیشنهای جنگو، **پروژه** نامیده میشوند. یک پروژه از اپلیکیشنها یا اپهای مختلفی تشکیل شده است. یک اپ، یک پکیج پایتونی است که مجموعهای از ویژگیها را برای یک هدف مشخص مانند ثبتنام یا تامبنیل عکسها تأمین میکند. به صورت ایدهال یک اپ باید چندبار مصرف باشد و بهسادگی بتواند با سایر اپها ارتباط برقرار کند. شما میتوانید به هر تعداد که بخواهید اپ بسازید. هرگز نگران اضافه کردن اپهای جدید یا بازنویسی اپهای موجود و تقسیم آنها به چند اپ جدید نباشید. یک پروژه معمول جنگو از ۱۵ تا ۲۰ اپ تشکیل شده است. تصمیم مهم در این مقطع این است که از یک پکیج شخص ثالث استفاده کنید یا آن را از ابتدا بسازید. پکیجهای شخص ثالث، که توسط شما نوشته نشدهاند، آماده استفاده هستند. اکثر پکیجها بسیار سریع نصب و تنظیم میشوند. شما میتوانید ظرف چند دقیقه از آنها استفاده کنید. در سوی دیگر، اگر اپ خود را بنویسید به این معنی است که باید مدلها، ویوها، تستها و سایر موارد را خودتان بنویسید. جنگو بین این دو نوع از اپ هیچ تفاوتی قائل نیست. **استفاده مجدد یا نوشتن از اول؟** یکی از بزرگترین ویژگیهای جنگو اکوسیستم اپهای شخص ثالث آن است. در زمان نوشتن این متن، [djangopackages.com](http://djangopackages.com/) بیش از ۳۵۰۰ پکیج را لیست کرده است. شما ممکن است در شرکتتان یا در کتابخانههای خصوصی حتی بیشتر از این هم پیدا کنید. زمانی که پروژه شما به اپهای کوچک تقسیم شود و بدانید که به چه نوع اپهایی نیاز دارید، وقت فراهم کردن اپها است، چه آنها را بنویسید یا اینکه از اپی موجود دوباره استفاده کنید. ممکن است نصب و استفاده از یک اپ آماده سادهتر به نظر برسد، اما به همین سادگی هم نیست. بیایید برای پروژه خودمان نگاهی به چند اپ شخص ثالث اعتبارسنجی بیندازیم و دلایلی را که از آنها برای پروژه سوپربوک استفاده نمیکنیم، فهرست کنیم: - **بیش از حد مهندسی شده برای نیازهای ما**: ما احساس میکنیم پکیج [python-social-auth](https://github.com/python-social-auth/social-app-django) با پشتیبانی لاگین به همه شبکههای اجتماعی، غیر ضروری است. - **بیش از حد مشخص شده**: استفاده از [Django-Facebook ](http://django-facebook.readthedocs.io/en/latest/installation.html) به معنی آن است که اعتبارسنجی خودمان را به امکانات یک وبسایت مشخص گره بزنیم. - **ایجاد خرابی در سایر اپها **: بعضی از اپها ممکن است تأثیرات ناخواستهای بر سایر اپها داشته باشند. - **وابستگیهای پایتونی**: برخی از اپها وابستگیهایی دارند که به طور فعال بهروزرسانی نمیشوند یا مورد تأیید نیستند. - **وابستگیهای غیر پایتونی**: برخی اپها وابستگیهای غیر پایتونی دارند مانند Redis و Node.js که سربارهایی برای انتشار وبسایت ایجاد میکنند. - **چندبار مصرف نبودن**: بسیاری از اپهای خودمان قابل استفاده نیستند چرا که برای استفاده مجدد نوشته نشدهاند و استفاده چندباره از آنها سخت است. هیچکدام از این پکیجها بد نیستند. اینها فقط نیاز فعلی ما را پاسخ نمیهند. این پکیجها ممکن است برای پروژه دیگری مورد استفاده قرار بگیرند. در مسأله ما اپ پیشساخته اعتبارسنجی جنگو، به خوبی کافی است. به عبارت دیگر، شما ممکن است ترجیح دهید از یک اپ شخص ثالث به یکی از دلایل زیر استفاده کنید: - **DRY**: دوباره چرخ را اختراع نکنید. از مزایای اپهای متن باز و به خوبی تستشده که احتمالاً بهتر از آن چیزی است که بخواهید از ابتدا بنویسید، استفاده کنید. - **برای فهمیدن زیادی سخت است**: آیا نیاز است که مدلهای شما یک درخت را شکل دهند اما همزمان از نظر دیتابیس بهینه باشند؟ از django-mptt استفاده کنید. - **بهترین یا توصیه شدهترین اپ برای یک هدف**: این توصیهها در طول زمان تغییر میکنند، اما پکیجی مانند django-debug-toolbar، توصیهشدهترین پکیج برای رفع عیب است. - **باتری اضافه**: بسیاری احساس میکنند که پکیجهایی مانند django-model-utils و django-extensions باید بخشی از بدنه اصلی فریمورک جنگو باشد. - **حداقل وابستگیها**: این همیشه نکته مثبتی است. اپهای کمتر به معنی تداخل ناخواسته کمتر بین سایر اپهاست و نگرانی کمتری ایجاد میکند. خب، آیا باید از یک اپ استفاده دوباره کرد و زمان را صرفهجویی کرد یا اینکه باید از اول نوشت؟ من پیشنهاد میکنم که اول یک اپ شحص ثالث را در یک محیط آزمایشی، امتحان کنید. اگر یک توسعهدهنده متوسط جنگو هستید، بخش بعد به شما میگوید که چگونه اپ را در محیط آزمایشی بررسی کنید. **محیط آزمایشی اپ من** در هر موقعیتی، شما با لیست متفاوتی از اپهای به دردبخور برای جنگو در پستهای وبلاگی مواجه میشوید. با اینحال بهترین راه برای تصمیمگیری در مورد استفاده از یک پکیج در یک پروژه، **پروتوتایپ** کردن آن است. حتی اگر شما یک محیط مجازی پایتون برای پروژه خود درست کرده باشید، نصب کردن و بررسی این اپها و بعد حذف آنها، ممکن است باز هم محیط مجازی شما را کثیف کند. بنابراین من معمولاً یک محیط مجازی جداگانه با پسوند _sandbox_ میسازم که به طور اختصاصی برای بررسی پکیجهاست. یک پروژه کوچک هم میسازم تا بهتر متوجه شوم که استفاده از این پکیج خاص چطور به ساده شدن کارها کمک میکند. در نهایت اگر از بررسی این اپ راضی بودم به کمک یک ابزار کنترل نسخه مانند گیت یک شاخه جدید برای اضافه کردن این اپ به پروژه، میسازم. سپس، کدنویسی و نوشتن تستها را در این شاخه جدید ادامه میدهم تا ویژگیهای لازم به پروژه اضافه شوند. در پایان این شاخه بازبینی شده و به شاخه اصلی اضافه میشود. **با کدام پکیجها پروژه را بسازیم؟** برای روشن شدن فرآیند، پروژه سوپربوک ما به طور کلی به اپهای زیر تقسیم میشود (البته لیست کامل نیست): - **اعتبارسنحی یا Authentication ** (اپ موجود django.auth) این اپ، ثبتنام، ورود و خروج کاربر را مدیریت میکند - **اکانتها یا Accounts** (اپ اختصاصی) این اپ اطلاعات اضافی پروفایل کاربر را مدیریت میکند - **پستها یا Posts** (اپ اختصاصی) این اپ پستها و کامنتها را مدیریت میکند در این مرحله، هر اپی که قرار است از ابتدا ساخته شود (با برچسب اپ اختصاصی)، و یا از اپهای شخص ثالث استفاده شود (اپ موجود)، مشخص شده است. در مراحل پیشرفت پروژه، ممکن است این موارد تغییر کند. با اینحال این لیست برای الان کافی است. ## بهینهترین روشها قبل از شروع پروژه موقعی که یک محیط توسعه را آماده میکنید، مطمئن شوید که این ابزارها را فراهم کردهاید: - **یک محیط مجازی تازه پایتون**: پایتون ۳ به صورت پیشفرض دارای ماژول venv است یا اینکه میتوانید virtualenv را نصب کنید. هر دو اینها جلوی آلوده شدن محیط عمومی کتابخانههای پایتون شما را میگیرند. اما [pipenv ](https://docs.pipenv.org/) ابزار پیشنهادی ماست (در این کتاب هم از آن استفاده میکنیم) تا وابستگیها و محیط مجازی پروژه را کنترل کند. - **کنترل نسخه**: همیشه از یک ابزار کنترل نسخه مانند گیت یا Mercurial استفاده کنید. این ابزارها نجاتدهنده هستند. به کمک آنها بدون نگرانی و ترس میتوانید تغییرات ایجاد کنید. - **انتخاب یک قالب برای پروژه**: قالب پیشفرض جنگو تنها انتخاب نیست. بر اساس نیازهایتان میتوانید از قالبهای دیگر مانند [Edge ](https://github.com/pydanny/cookiecutter-django) یا [Cookiecutter](https://github.com/pydanny/cookiecutter-django) استفاده کنید. - **پایپ لاینهای انتشار**: من معمولاً کمی دیرتر نگران این موضوع میشوم. اما یک فرآیند انتشار سریع میتواند توسعه را سرعت ببخشد. من Fabric (یک نسخه پایتون ۳ به نام fabric3 دارد) یا Ansible را ترجیح میدهم. ## سوپربوک، مأموریتی که باید بپذیرید این کتاب به رویکرد عملی و کاربردی برای پیادهسازی الگوهای طراحی جنگو و روشهای بهینه آن، به کمک مثالها، باور دارد. برای هماهنگی بیشتر، تمام مثالها در مورد ساخت یک پروژه شبکه اجتماعی به نام سوپربوک است. سوپربوک، به طور خاص بر روی بخش ویژه و اغلب نادیده گرفته شدهای از افرادی که دارای ابرقدرتهای استثنایی هستند، متمرکز است. شما یکی از توسعهدهندگان تیمی متشکل از سایر توسعهدهندگان، طراحان وب، یک مدیر بازاریابی و یک مدیر پروژه هستید. پروژه روی آخرین نسخه پایتون (نسخه 3.6) و جنگو (نسخه 2.0) در زمان نوشتن کتاب، توسعه داده میشود. از آنجایی که انتخاب پایتون ۳ ممکن است موضوعی بحث برانگیز باشد، شایسته است که توضیح بیشتری داده شود. **چرا پایتون ۳؟** در حالی که توسعه پایتون 3.0 در سال ۲۰۰۶ شروع شد، اولین نسخه آن در ۳ دسامبر ۲۰۰۸ منتشر شد. دلیل اصلی برای توسعه دادن یک نسخه هماهنگ با نسخههای قبلی این موارد بود: هماهنگی تمام رشتهها با یونیکد، افزایش استفاده از iteratorها، کنار گذاشتن ویژگیهای منسوح شده مانند کلاسهای قدیمی، و برخی قواعد دستوری جدید مانند عبارتهای nonlocal. بازخوردها به پایتون ۳ در جامعه جنگو کمی درهم آمیخته بود. اگرچه تغییرات زبان بین نسخه ۲ و ۳ کم بود (و در طول زمان هم کاهش یافت)، انتقال تمام کدهای جنگو، یک مهاجرت واقعاً بزرگ بود. در ۱۳ فوریه، جنگو 1.5، اولین نسخه منتشر شدهای بود که پایتون ۳ را پشتیبانی میکرد. توسعهدهندگان اصلی اعلام کردهاند که در آینده، جنگو فقط برای پایتون ۳ نوشته خواهد شد. به دلایل زیر، پایتون ۳ انتخاب ایدهآلی برای این کتاب است: - **دستور زبان بهتر**: دستور زبان پایتون ۳ بسیاری از دستورات زشت مانند _izip_، _xrange_ و \_\_unicode\_\_ را با دستورات تمیزتری مانند zip، range و \_\_str\_\_ جابجا کردهاست. - **حمایت شخص ثالث کافی**: بیش از ۹۰ درصد از ۲۰۰ کتابخانه مهم شخص ثالث، از پایتون ۳ پشتیبانی میکنند (به Python 3 Wall of Superpowers نگاهی بیندازید). - **نداشتن کد قدیمی**: ما یک پروژه را از ابتدا شروع میکنیم و نیازی نداریم با کدهای باقی مانده از قبل سر و کار داشته باشیم. - **زبان پیشفرض در پلتفرمهای جدید**: الان به صورت پیشفرض مفسر پایتون ۳ در Arch Linux وجود دارد و اوبونتو و فدورا هم در نسخههای بعدی آن را به صورت پیشفرض فعال خواهند کرد. - **سادهتر است**: از دیدگاه توسعه بر اساس جنگو، تغییرات این دو بسیار کم هستند و میتوان ظرف چند دقیقه آنها را فرا گرفت. نکته آخر مهم است. حتی اگر شما از پایتون ۲ استفاده کنید، این کتاب برای شما قابل استفاده است. ضمیمه A را بخوانید تا تفاوتها را بفهمید. لازم است تغییرات کمی بدهید تا کدها را برای پایتون ۲ آماده کنید. **کدام نسخه جنگو را استفاده کنیم** جنگو الان یک برنامه زمانی استاندارد شده برای توسعه در سه مدل مختلف دارد: - **نسخه ویژگی (Feature)**: این نسخهها ویژگیهای جدید دارند یا ویژگیهای موجود را ارتقا دادهاند. این نسخهها هر ۸ ماه یکبار منتشر میشوند و یک پشتیبانی ۱۶ ماهه از زمان انتشار دارند. شمارههای آنها به صورت A.B است (دقت کنید که نسخه مینور ندارند) - **نسخه پشتیبانی بلندمدت(Long-Term Support)**: اینها یک نوع خاص از نسخه ویژگی هستند که یک دوره پشتیبانی ۳ ساله از زمان انتشار دارند. این نسخهها هر دو سال یکبار منتشر میشوند. شماره این نسخهها به شکل A.2 است (هر سه نسخه ویژگی، یک نسخه LTS خواهد بود). نسخههای بلند مدت، چند ماه با هم همپوشانی دارند تا مهاجرت از یک نسخه به نسخه دیگر با آرامش انجام شود. - **نسخه رفع عیب (Patch)**: این نسخهها برای رفع عیب یا اصلاح مشکلات امنیتی هستند. این نسخهها بلافاصه منتشر میشوند. چون به طور معمول تغییرات زیادی ندارند بهروزرسانی به این نسخهها معمولاً بدون مشکل است. این نسخهها شمارههایی به شکل A.B.C دارند. این نقشه راه توسعه جنگو، تصویر شفافتری از رویکرد توسعه جنگو ارائه میدهد:  نقشه انتشار نسخههای جنگو جنگو 1.11 LTS آخرین نسخهای خواهد بود که پایتون ۲ را پشتیبانی میکند و این نسخه تا آپریل ۲۰۲۰ پشتیبانی خواهد شد. نسخههای بعدی فقط از پایتون ۳ پشتیبانی خواهند کرد. یک نسخه جنگو مناسب برای شما، بستگی به این دارد که هر چند وقت بکبار میتوانید جنگو را آپدیت کنید و به کدام ویژگیها نیاز دارید. اگر پروژه شما به صورت فعال در حال توسعه است و نسخه جنگو میتواند هر ۱۶ ماه یکبار آپدیت شود، پس شما میتوانید آخرین نسخه ویژگی را نصب کنید فارغ از اینکه LTS هست یا نه. در غیر اینصورت، اگر پروژه شما فقط گاهی توسعه داده میشود، پس باید آخرین نسخه LTS را انتخاب کنید. به روزرسانی وابستگیهای پروژه جنگو از یک نسخه ویژگی به نسخه ویژگی دیگر ممکن است تلاشی غیر ضروری باشد. بنابراین توضیحات هر نسخه را مطالعه کنید و براساس آن برنامهریزی کنید. این کتاب تا حد ممکن از امکانات جنگو 2.0 استفاده میکند. **شروع پروژه** این بخش دارای دستورالعملهای نصب پروژه سوپربوک است که شامل تمام کدهای استفاده شده در کتاب است. میتوانید برای دیدن آخرین یادداشتها در مورد نصب پروژه، فایل README.md را در [گیتهاب](https://github.com/DjangoPatternsBook/superbook2) ببینید. ما از ابزار pipenv برای ساخت یک محیط مجازی و نصب وابستگیها استفاده میکنیم.  _برای هر پروژه جنگو یک محیط مجازی جداگانه بسازید_ ابتدا، پروژه را از گیتهاب کپی کنید: **$ git clone https://github.com/DjangoPatternsBook/superbook2.git** سپس، pipenv را بر اساس توصیه مستندات خودش، به صورت لوکال یا به صورت عمومی، اما خارج از virtualenv، به کمک دستورات زیر نصب کنید: **$ pip install -U pip $ pip install pipenv** حالا به پوشه پروژه بروید و وابستگیها را نصب کنید: **$ cd superbook2!** **$ pipenv install --dev** سپس وارد شل بشوید تا از محیط مجازی تازه ساخته شده با تمام وابستگیها، استفاده کنید: **$ pipenv shell** در نهایت، پروژه را با دستورات مدیریتی جنگو، اجرا کنید: **$ cd src** **$ python manage.py migrate** **$ python manage.py createsuperuser** **$ python manage.py runserver** میتوانید به آدرس http://127.0.0.1:8000 که در ترمینال نمایش دادهشده بروید و از وبسایت استفاده کنید. ## خلاصه تازهکارها معمولاً یک فرآیند جمعآوری نیازمندیهای خوب را دستکم میگیرند. همزمان بسیار مهم است که بیش از حد درگیر جزییات نشد، چرا که برنامهنویسی ذاتاً یک فرآیند اکتشافی است. پروژههای موفق، پیش از توسعه، زمان مناسبی را برای برنامهریزی و آمادهسازی صرف میکنند در نتیجه بیشترین منافع را ایجاد میکنند. ما درمورد جنبههای مختلفی از طراحی اپلیکیشن بحث کردیم مانند ساختن ماکت تعاملی یا تقسیم پروژه به بخشهای چندبار مصرف به نام اپ. همچنین برای پروژه مثالی سوپربوک، مراحل راهاندازی را مطرح کردیم. در بخشهای بعدی به هر قسمت از جنگو با جزییات بیشتری نگاه خواهیم کرد و الگوهای طراحی و روشهای بهینه در مورد آنها را یاد خواهیم گرفت. ================================================ FILE: 03-Models/README.md ================================================ # مدلها در این بخش به بحثهای زیر میپردازیم: - اهمیت مدلها - نمودار کلاسها - الگویهای ساختاری مدل - الگوهای رفتاری مدل - مایگریشنها (مهاجرتها) من یک بار به یک استارت آپ تحلیل داده، در مراحل اولیهشان مشاوره دادم. با وجود اینکه گرفتن دیتا به یک بازه زمانی اخیر محدود شده بود، آنها مشکلات کارایی(performance) داشتند. باز کردن برخی صفحات بعضی اوقات چند ثانیه طول میکشید. بعد از بررسی معماریشان، به تظر میآمد که مشکل از مدل دادهشان بود. در عین حال، مهاجرت کردن(migrating) و تبدیل پتابایتهایی از دیتای ساختاریافته و زنده، غیر ممکن به نظر میرسید. > "فلوچارت خود را به من نشان بدهید و جداول خود را پنهان کنید و من همچنان مبهوت خواهم ماند. جداول خود را به من نشان دهید و من معمولاً نیازی به فلوچارتها نخواهم داشت، آنها آشکار خواهند بود." (فرد بروکز، The Mythical Man-month) به طور سنتی، طراحی کد بر اساس دادههای فکر شده همیشه توصیه میشود. اما در این عصر دادههای بزرگ، این توصیهها مرتبطتر هم شده است. اگر مدل داده شما ضعیف طراحی شده باشد، حجم دادهها در نهایت باعث مشکلات مقیاس پذیری و نگهداری میشود. توصیه میکنم از ضرب المثل زیر در مورد نحوه تعادل کد و داده استفاده کنید: > **قانون بازنمایی** (Rule of Representation): دانش را در دیتا قرار بدهید تا منطق برنامه قدرتمند و احمق باشد. فکر کنید که چطور میتوانید پیچیدگی را از کد به دیتا ببرید. همیشه فهمیدن منطق کد از فهمیدن منطق دیتا سختتر است. یونیکس از همین فلسفه به خوبی استفاده کرده است تا تعداد زیادی ابزار ساده ایجاد شود که میتوانند با هم ترکیب (پایپ) شوند و هر گونه تغییر روی دیتاهای متنی را انجام دهند. در نهایت، دادهها طول عمر بیشتری نسبت به کد دارند. شرکتها ممکن است تصمیم بگیرند کل پایگاههای کد را بازنویسی کنند زیرا دیگر نیازهای آنها را برآورده نمیکنند، اما پایگاههای داده معمولاً نگهداری میشوند و حتی در بین برنامهها به اشتراک گذاشته میشوند. پایگاههای دادهای که به خوبی طراحی شده اند بیشتر یک هنر هستند تا یک علم. این فصل برخی از اصول اساسی مانند نرمال سازی(Normalization) و بهترین شیوهها در مورد سازماندهی دادهها را به شما ارائه میدهد. اما قبل از آن، بیایید ببینیم مدلهای داده در برنامه جنگو کجا قرار میگیرند. # ام بزرگ تر از وی و سی بزرگ تر از وی است در جنگو، مدلها کلاسهایی هستند که روشی شیءگرا برای برخورد با پایگاههای داده ارائه میکنند. به طور معمول، هر کلاس به یک جدول پایگاه داده و هر ویژگی به یک ستون پایگاه داده اشاره دارد. میتوانید با استفاده از یک API که به طور خودکار تولید میشود، کوئریهایی را در این جداول ایجاد کنید. مدلها میتوانند پایه بسیاری از اجزای دیگر باشند. هنگامی که یک مدل دارید، میتوانید به سرعت ادمینهای مدل، فرمهای مدل و انواع نماهای عمومیرا استخراج کنید. در هر مورد، باید یک یا دو خط کد بنویسید تا خیلی هم جادویی به نظر نرسد. همچنین، مدلها در مکانهای بیشتری از آنچه انتظار دارید، استفاده میشوند. این به این دلیل است که جنگو را میتوان به روشهای مختلفی اجرا کرد. برخی از نقاط ورود جنگو به شرح زیر است: - جریان آشتای درخواست-پاسخ وب - شل اینترکتیو جنگو - دستورات مدیریتی (management commands) - اسکریپتهای تست - صفهای وظایف ناهمزمان همانند سلری تقریباً در همه این موارد، ماژولهای مدل وارد میشوند (به عنوان بخشی از **django.setup()**). از این رو، بهتر است مدلهای خود را از هر گونه وابستگی غیر ضروری یا هر جزء دیگر جنگو، مانند viewها دور نگه دارید. به طور خلاصه، طراحی درست مدلهای شما، بسیار مهم است. حالا بیایید با طراحی مدل SuperBook شروع کنیم. #### کیف قهوهای نهار: یادداشت نویسنده: پیشروی این پروژه سوپرکتاب در یک بخش مثل این نمایش داده خواهد شد. شاید شما از جعبه عبور کنید, ولی بینشها و تجربههای زیاد و درامای کار کردن روی یک پروژه وب اپلیکیشن را از دست میدهید. هفته اول استیو با مشتریش، هوش ابرقهرمانی و مانیتورینگ (شیم) به صورت کوتاه، خیلی قاطی پاتی بود. دفتر فوقالعاده آیندهنگر بود، اما انجام هر کاری به صدها تائید و امضا نیاز داشت. استیو به عنوان توسعهدهنده اصلی جنگو، راهاندازی یک سرور توسعه متوسط را که میزبان چهار ماشین مجازی بود بعد از دو روز به پایان رسانده بود. صبح روز بعد، خود دستگاه ناپدید شده بود. یک ربات به اندازه ماشین لباسشویی در همان نزدیکی گفت که به دلیل نصب نرم افزار تایید نشده به بخش پزشکی قانونی منتقل شده است. با این حال، مدیر ارشد فناوری، هارت، کمک بزرگی بود. او درخواست کرد دستگاه تا یک ساعت دیگر با تمام سیستمهای نصبشده سالم برگردانده شود. او همچنین پیش تأییدیههایی را برای پروژه سوپربوک ارسال کرده بود تا از چنین موانعی در آینده جلوگیری کند. بعد از ظهر همان روز، استیو یک کیف قهوهای ناهار همراهش بود. یک کت بلیزر بژ و شلوار جین آبی روشن پوشیده بود. هارت به موقع رسید. علیرغم اینکه از بیشتر مردم بلندتر بود و سرش تراشیده بود، خونسرد و خوش برخورد به نظر میرسید. او پرسید که آیا استیو تلاش قبلی برای ساخت پایگاه داده ابرقهرمانی در دهه شصت را بررسی کرده است؟ استیو گفت: "اوه بله، پروژه Sentinel، درست است؟". "به نظر میرسد پایگاه داده به عنوان یک مدل *Entity-Attribute-Value* طراحی شده است، چیزی که من آن را یک ضد الگو میدانم. شاید آنها در آن روزها تصور بسیار کمی در مورد ویژگیهای یک ابرقهرمان داشتند". هارت در زمان شنیدن آخرین جمله تقریباً خم شد. با صدای کمی آهسته تر گفت: "درست میگویی. من چنین تصوری ندارم. علاوه بر این، آنها فقط دو روز به من فرصت دادند تا همه چیز را طراحی کنم. من معتقدم به معنای واقعی کلمه یک بمب هستهای در جایی تیک تاک میکند." دهان استیو کاملاً باز بود و ساندویچش در ورودی آن یخ زده بود. هارت لبخند زد. "مطمئنا بهترین کار من نیست. زمانی که از حدود یک میلیارد ورودی عبور کرد، روزها طول میکشد تا هر نوع تحلیلی را روی آن پایگاه داده لعنتی اجرا کنیم. سوپر بوک در عرض چند ثانیه آن را انجام میدهد، درست است؟" استیو به آرامی سر تکان داد. او هرگز تصور نمیکرد که در وهله اول حدود یک میلیارد ابرقهرمان وجود داشته باشد. ### شکار مدلها در اینجا اولین برش از شناسایی مدلها در سوپربوک است. به عنوان نمونه برای یک تلاش اولیه، ما فقط مدلهای اساسی و روابط آنها را در قالب یک نمودار ساده کلاسها نشان دادهایم:  بیایید یک لحظه مدلها را فراموش کنیم و در مورد اشیایی که مدل سازی میکنیم صحبت کنیم. هر کاربر یک پروفایل دارد. یک کاربر میتواند چندین نظر یا چندین پست بگذارد. یک لایک میتواند مربوط به یک ترکیب کاربر/پست باشد. توصیه میشود نموداری کلاسی مانند این از مدلهای خود ترسیم کنید. ممکن است در این مرحله ویژگیهای کلاس وجود نداشته باشد، اما میتوانید بعداً آنها را توضیح دهید. هنگامی که کل پروژه در نمودار نشان داده میشود، جداسازی برنامهها آسان تر میشود. اینجا چند نکته وجود دارد تا این بازنمایی را انجام بدهیم: * اسمها معمولاً تبدیل به هویت مدلها میشود. * مستطیلها که هر موجودیت را نشان میدهند به مدلها تبدیل میشوند. * خطهای متصل کننده که دو جهتی هستند و سه نوع از روابط را در جنگو تعریف میکنند: یک-به-یک , یک-به-خیلی (با کلید خارجی یا Foreign Keys پیاده سازی میشوند) و خیلی-به-خیلی * بخشی که رابطه یک-به-خیلی را تعریف میکند در سمت **Entity-relationship model (ER-model)** قرار دارد. به عبارتی دیگر، طرف n جایی هست که کلید خارجی تعریف میشود. نمودار کلاسها میتوانند به کدهای جنگو مانند زیر ارتباط داده شوند. (که بین چندین اپ، پخش خواهند شد): ``` class Profile(models.Model): user = models.OneToOneField(User) class Post(models.Model): posted_by = models.ForeignKey(User) class Comment(models.Model): commented_by = models.ForeignKey(User) for_post = models.ForeignKey(Post) class Like(models.Model): liked_by = models.ForeignKey(User) post = models.ForeignKey(Post) ``` بعداً مستقیماً به **User** ارجاع نخواهیم داد، بلکه از **settings.AUTH_USER_MODEL** استفاده میکنیم. همچنین در این مرحله نگران ویژگیهای فیلد مانند **on_delete** یا **primary_key** نیستیم. به زودی به این جزئیات خواهیم پرداخت. # تقسیم کردن فایل models.py به چندین فایل مانند بسیاری از اجزای جنگو، یک فایل models.py بزرگ را میتوان به چندین فایل در یک پکیج تقسیم کرد. یک پکیج به صورت دایرکتوری پیاده سازی میشود که میتواند حاوی چندین فایل باشد یکی از آنها باید فایلی با نام خاص به نام `__init__.py` باشد. این فایل میتواند خالی باشد، اما باید وجود داشته باشد. همه تعاریفی که باید در سطح پکیج نمایش داده شوند باید در `__init__.py` به صورت عمومی (global scope) تعریف شوند. به عنوان مثال، اگر models.py را به کلاسهای جداگانه تقسیم کنیم، در فایلهای مربوطه در داخل زیرشاخه مدلها مانند postable.py، post.py، و comment.py، ساختار دایرکتوری به شکل زیر خواهد بود: models/ - comment.py - ــinitــ.py - postable.py - post.py برای اطمینان از اینکه همه مدلها به درستی فراخوانی شده اند فایل ، `__init__.py` باید خطوط زیر را داشته باشد: ``` from postable import Postable from post import Post from comment import Comment ``` اکنون میتوانید models.Post را مانند قبل فراخوانی کنید. هر کد دیگری که در فایل `__init__.py` باشد هنگام فراخوانی پکیج، اجرا میشود. بنابراین، این فایل، محل ایدهآلی برای تعریف مقادیر اولیه در سطح پکیج است. # الگوهای ساختاری این بخش شامل چندین الگوی طراحی است که میتواند به شما در طراحی و ساختار مدلهای خود کمک کند. الگوهای ساختاری ذکر شده در اینجا به شما کمک میکند تا روابط بین مدلها را به طور موثرتری درک کنید. ## الگوها — مدلهای نرمال شده **مشکل:** به صورت ساختاری, هر کپی از مدلها، شامل دادههای تکراری هستند که باعث ناسازگاری دادهها میشود **راه حل** مدلهای خود را از طریق نرمال سازی به مدلهای کوچکتر تقسیم کنید. این مدلها را با روابط منطقی به هم وصل کنید. ## جزییات مشکل تصور کنید کسی جدول پست ما را (با حذف ستونهای خاص) به روش زیر طراحی کند:  امیدوارم که به اسمهای ابرقهرمانها که به صورت ناسازگار در ستون اول( و کاپیتان تمپری که صبر ندارد) آمده توجه کردهباشید. اگه به اولین ستون نگاه کنیم, ما مطمئن نیستیم که کدام روش هجی کردن درست است، **Captain Temper** یا **Capt. Temper**. این نوعی از افزونگی داده است که ما دوست داریم توسط نرمال سازی دیتا از بین ببریم. ## جزییات راه حل قبل از اینکه نگاهی به راه حل کاملا نرمال شده بیندازیم، اجازه دهید یک توضیح مختصر در مورد نرمال سازی پایگاه داده در زمینه مدلهای جنگو داشته باشیم. ### سه قدم در نرمال سازی عادی سازی به شما کمک میکند تا دادهها را به طور موثر ذخیره کنید. هنگامی که مدلهای شما به طور کامل نرمالسازی شدند، دادههای اضافی نخواهند داشت و هر مدل باید حاوی دادههایی باشد که فقط از نظر منطقی به آن مرتبط هستند. برای ارائه یک مثال سریع، اگر میخواهیم جدول پست را عادی کنیم تا بتوانیم بدون ابهام به ابرقهرمانی که آن پیام را ارسال کرده است اشاره کنیم، باید جزئیات کاربر را در یک جدول جداگانه جدا کنیم. جنگو قبلاً جدول کاربر را به طور پیش فرض ایجاد میکند. بنابراین، همانطور که در جدول زیر نشان داده شده است، فقط باید به شناسه کاربری که پیام را در ستون اول ارسال کرده است مراجعه کنید:  اکنون نه تنها مشخص است که سه پیام توسط یک کاربر ارسال شده است (با یک شناسه کاربری دلخواه)، بلکه میتوانیم با جستجوی جدول کاربر نام صحیح آن کاربر را نیز پیدا کنیم. به طور کلی، شما مدلهای خود را به گونهای طراحی میکنید که کاملاً نرمال شده باشند و سپس به دلیل بهبود عملکرد، به طور انتخابی برخی از آنها را از حالت نرمال خارج میکنید (برای اطلاع از علت آن، به بخش بعدی در مورد عملکرد مراجعه کنید). در پایگاههای داده، **فرمهای نرمال** مجموعهای از دستورالعملها هستند که میتوان آنها را برای اطمینان از نرمالسازی جدول به کار برد. فرمهای معمولی که معمولاً یافت میشوند، فرمهای نرمال نوع اول،نوع دوم و نوع سوم هستند، اگرچه میتوانند تا پنج مرحله هم، نرمال بشوند. در مثال بعدی,ما یک جدول را نرمال سازی میکنیم و مدلهای جنگو متناظر را میسازیم. صفحه گستردهای به نام Sightings را تصور کنید که اولین باری که فردی یک ابرقهرمان را با استفاده از قدرت یا توانایی مافوق بشری میبیند، وی را در این صفحه، فهرست میکند. هر ورودی در این صفحه گسترده، به منشاء ابرقهرمان، نوع قدرت وی و محل اولین مشاهده که شامل از جمله طول و عرض جغرافیایی است، اشاره میکند:  دیتای جغرافیای زیر از [http://www.golombek.com/locations.html](http://www.golombek.com/locations.html) به دست آمده است. ## فرم نرمال نوع اول (1NF) - هیچ خصوصیتی(سلول) با داده تکراری وجود نداشته باشد - یک کلید اصلی(پرایمری) به صورت یک ستون یا چندین ستونی(کامپوزیت کی) تعریف شود. بیایید سعی کنیم صفحه گسترده خود را به یک جدول پایگاه داده تبدیل کنیم. بدیهی است که ستون **Power** ما قانون اول را زیر پا میگذارد. جدول به روز شده در اینجا اولین فرم نرمال بودن را برآورده میکند. کلید اصلی (با علامت *) ترکیبی از **Name** و **Power** است که باید برای هر ردیف منحصر به فرد باشد:   ## فرم نرمال نوع دوم (2NF) فرم نرمال نوع دوم باید تمام شرایط فرم نرمال اول را برآورده کند. علاوه بر این، باید این شرط را برآورده کند که تمام ستونهای کلید غیر اصلی، باید به کل کلید اصلی وابسته باشند. در جدول قبلی توجه کنید که Origin فقط به ابرقهرمان یعنی Name بستگی دارد. مهم نیست در مورد کدام Power صحبت میکنیم. بنابراین، Origin کاملاً به کلید اولیه ترکیبی - Name و Power وابسته نیست. بیایید فقط اطلاعات مبدا را در یک جدول جداگانه به نام Origin استخراج کنیم، همانطور که در اینجا نشان داده شده است:  حالا جدول Sightings را طوری تغییر میدهیم که با فرم نرمال نوع دوم هم تطابق داشته باشد.  ## فرم نرمال نوع سوم (3NF) در فرم نرمال نوع سوم، جداول باید فرم نرمال نوع دوم را برآورده کنند و علاوه بر این باید شرایطی را داشته باشند که تمام ستونهای کلید غیراصولی باید مستقیماً به کل کلید اصلی وابسته باشند و در ضمن باید مستقل از یکدیگر باشند. برای لحظهای به ستون **Country** فکر کنید. با توجه به **Longitude** و **Latitude**، میتوانید به راحتی ستون **Country** را استخراج کنید. حتی اگر کشوری که در آن یک ابرقدرت دیده شده است به کلید اولیه ترکیبی Name-Power وابسته است، اما فقط به طور غیرمستقیم به آنها وابسته است. بنابراین، اجازه دهید جزئیات مکان را در جدول جداگانه کشورها به صورت زیر، جدا کنیم:  حالا جدول Sightings ما در سومین نوع نرمال سازی قرار دارد:  مانند قبل، نام ابرقهرمان را با User ID مربوطه جایگزین کرده ایم که میتواند برای ارجاع به جدول کاربر استفاده شود. # مدلهای جنگو حالا میتوانیم نگاه کنیم که این حدولهای نرمال سازی شده چطور میتوانند به صورت مدلهای جنگو نمایش داده بشوند. کلیدهای ترکیبی یا کامپوزیت کیها به صورت مستقیم در جنگو پشتیبانی نمیشوند.راه حل استفاده شده در اینجا اعمال کلیدهای جایگزین و مشخص کردن ویژگی *unique_together* در کلاس *Meta* است: ```python class Origin(models.Model): superhero = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE) origin = models.CharField(max_length=100) def __str__(self): return "{}'s orgin: {}".format(self.superhero, self.origin) class Location(models.Model): latitude = models.FloatField() longitude = models.FloatField() country = models.CharField(max_length=100) def __str__(self): return "{}: ({}, {})".format( self.country, self.latitude, self.longitude ) class Meta: unique_together = ("latitude", "longitude") class Sighting(models.Model): superhero = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE) power = models.CharField(max_length=100) location = models.ForeignKey(Location, on_delete=models.CASCADE) sighted_on = models.DateTimeField() def __str__(self): return "{}'s power {} sighted at: {} on {}".format( self.superhero, self.power, self.location.country, self.sighted_on ) class Meta: unique_together = ("superhero", "power") ``` # کارایی و نرمال سازی نکردن (denormalization) نرمال سازی میتواند بر کارایی، تأثیر منفی بگذارد. با افزایش تعداد مدلها، تعداد پیوستهای مورد نیاز برای پاسخ به یک کوئری نیز افزایش مییابد. به عنوان مثال، برای یافتن تعداد ابرقهرمانان با قابلیت Freeze در ایالات متحده، باید به چهار جدول درخواست ارسال شود. قبل از نرمال سازی، میتوانستیم همه اطلاعات را با کوئری فرستادن به یک جدول، به دست بیاوریم. شما باید مدلهای خود را طوری طراحی کنید که دادهها نرمال نگه داشته شوند. این کار، یکپارچگی دادهها را حفظ میکند. با این حال، اگر سایت شما با مشکلات مقیاس پذیری مواجه است، میتوانید به طور انتخابی دادهها را از آن مدلها استخراج کنید تا دادههای دینرمال ایجاد کنید. ##### بهترین الگوها *در حال طراحی نرمالسازی کنید, ولی برای بهینه سازی دی نرمالایز کنید* به عنوان مثال، اگر تعداد مشاهدات در یک کشور خاص بسیار زیاد است، آن را به عنوان یک فیلد اضافی به مدل *Location* اضافه کنید. اکنون، میتوانید کوئریهای دیگر را با استفاده از **object-relational mapping (ORM)**، در جنگو، بر خلاف مقدار ذخیره شده، اضافه کنید. با این حال، هر بار که یک مشاهده را اضافه یا حذف میکنید، باید این تعداد را به روز کنید. شما یا باید این محاسبه تعداد را به متد *save* در مدل Sighting اضافه کنید یا یک سیگنال اضافه کنید یا با استفاده از یک روش انجام کار ناهمزمان، محاسبات را انجام دهید. اگر کوئری پیچیدهای دارید که چندین جدول را در بر میگیرد، مانند تعداد ابرقدرتها بر اساس کشور، ایجاد یک جدول دینرمال شده جداگانه ممکن است عملکرد را بهبود بخشد. به طور معمول، این جدول در یک پایگاه داده دررون-حافظه یا کش سریعتر، اجرا میشود. مانند قبل، هر بار که دادههای مدلهای نرمالشده شما تغییر میکند، باید این جدول دینرمال شده را بهروزرسانی کنیم (در غیر این صورت با مشکل دوستنداشتنی Cache-Invalidation مواجه خواهید شد). دینرمال کردن بهطور شگفتانگیزی در وبسایتهای بزرگ متداول است، زیرا تعادلی بین سرعت و فضا است. امروزه فضا ارزان است، اما سرعت برای تجربه کاربر بسیار مهم است. بنابراین، اگر پاسخ کوئری شما بیش از حد طول میکشد، ممکن است بخواهید آن را در نظر بگیرید. # آیا همیشه باید نرمالسازی کنیم؟ نرمالسازی بیش از حد لزوماً چیز خوبی نیست. گاهی اوقات، میتواند باعث به وجود آمدن جداول غیر ضروری شود که به روز رسانیها و جستجوها را پیچیده کند. به عنوان مثال، مدل کاربری شما ممکن است چندین فیلد برای آدرس خانه آنها داشته باشد. به طور دقیق، میتوانید این فیلدها را به یک مدل آدرس نرمال کنید. با این حال، در بسیاری از موارد، معرفی یک جدول اضافی به پایگاه داده غیر ضروری خواهد بود. بهجای هدف نرمالسازیشدهترین طرح، هر فرصتی را برای نرمالسازی با دقت بسنجید و قبل از ایجاد آن، فواید و مضراتش را در نظر بگیرید. # الگو — مدلهای میکسین **مشکل:** مدلهای متمایز دارای فیلدها و/یا روشهای مشابه هستند که اصل DRY را نقض میکنند. **راه حل:** زمینهها و روشهای مشابه و تکراری را به مدلهای میکسین قابل استفاده مجدد، تقسیم کنید. #### جزییات مشکل هنگام طراحی مدلها، ممکن است ویژگیها یا رفتارهای مشترک مشخصی را پیدا کنید که در کلاسهای مدل به اشتراک گذاشته شده است. به عنوان مثال، یک مدل پست و نظر باید تاریخ ایجاد و تاریخ اصلاح آن را پیگیری کند. کپی و چسباندن دستی فیلدها و روش مرتبط با آنها یک رویکرد بسیار DRY نیست. از آنجایی که مدلهای جنگو کلاس هستند، رویکردهای شی گرا مانند ترکیب و ارث راه حلهای ممکن هستند. با این حال، ترکیبات (با داشتن یک ویژگی که حاوی نمونهای از کلاس مشترک است) برای دسترسی به فیلدها به یک سطح غیرمستقیم اضافی نیاز دارند. ارث میتواند مشکل ساز شود. ما میتوانیم از یک کلاس پایه مشترک برای پست و نظرات استفاده کنیم. با این حال، سه نوع ارث در جنگو وجود دارد: عینی concrete، انتزاعی abstract و پروکسی proxy. **وراثت عینی** با ارث بری از کلاس پایه درست مانند آنچه که معمولاً در کلاسهای پایتون انجام میدهید کار میکند. با این حال، در جنگو، این کلاس پایه در یک جدول جداگانه ثبت میشود. هر بار که به فیلدهای پایه دسترسی پیدا میکنید، به یک عملیات join نیاز است. این اتفاق منجر به افت شدید کارایی میشود. **وراثت پراکسی** فقط میتواند رفتار جدیدی را به کلاس والد اضافه کند. شما نمی توانید فیلدهای جدید اضافه کنید. از این رو برای این وضعیت چندان مفید نیست. در نهایت، ما با وراثت Abstract باقی میمانیم. #### جزییات راه حل وراثت انتزاعی یک راه حل ظریف است که از کلاسهای پایه Abstract ویژه برای به اشتراک گذاشتن دادهها و رفتار بین مدلها استفاده میکند. وقتی یک کلاس پایه انتزاعی را در جنگو تعریف میکنید، که با کلاسهای پایه انتزاعی (ABC) در پایتون یکسان نیست، هیچ جدول مربوطه در پایگاه داده ایجاد نمی کند. در عوض، این فیلدها در کلاسهای غیر انتزاعی مشتق شده ایجاد میشوند. دسترسی به فیلدهای کلاس پایه انتزاعی نیازی به دستور *JOIN* ندارد. جداول به دست آمده نیز دارای فیلدهای مدیریت شده هستند. با توجه به این مزایا، اکثر پروژههای جنگو از کلاسهای پایه انتزاعی برای پیاده سازی فیلدها یا روشهای مشابه و تکراری استفاده میکنند. محدودیتهای مدلهای انتزاعی به شرح زیر است: - نمی توانند کلید خارجی یا فیلد چند به چند از مدل دیگری داشته باشند - از آنها نمی توان نمونه (instance) تهیه کرد یا آنها را ذخیره کرد - آنها را نمی توان مستقیماً در کوئری استفاده کرد زیرا مدیری (class manager) ندارند در اینجا نحوه طراحی کلاسهای پست و نظرات، در ابتدا با یک کلاس پایه انتزاعی، آمده است: ``` class Postable(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) message = models.TextField(max_length=500) class Meta: abstract = True class Post(Postable): ... class Comment(Postable): ... ``` برای تبدیل یک مدل به یک کلاس پایه انتزاعی، باید *abstract = True* را در کلاس *Meta* در داخل مدل اضافه کنید. در اینجا، *Postable* یک کلاس پایه انتزاعی است. با این حال، خیلی قابل استفاده مجدد نیست. در واقع، اگر کلاسی وجود داشته باشد که فقط فیلد *created* و *modified* را داشته باشد، میتوانیم تقریباً در هر مدلی که به مهر زمانی نیاز دارد، از آن عملکرد مهر زمانی مجدداً استفاده کنیم. در چنین مواردی، ما معمولا یک مدل میکسین را تعریف میکنیم. ##### میکسینهای مدل میکسینهای مدل، کلاسهای انتزاعی هستند که میتوانند به عنوان کلاس والد یک مدل اضافه شوند. پایتون بر خلاف زبانهای دیگر مانند جاوا از چندین وراثت پشتیبانی میکند. از این رو، میتوانید هر تعداد کلاس والد را برای یک مدل فهرست کنید. میکسینها باید بسیار واضح باشند و به راحتی ترکیب شوند. اگر یک میکسین را به صورت کلاسهای پایه تعریف کنید باید به درستی کار کند. از این نظر رفتار آنها بیشتر به ترکیب شبیه است تا وراثت. میکسینهای کوچکتر بهتر هستند. هر زمان که یک میکسین بزرگ شد و اصل مسئولیت واحد را نقض کرد، آن را در کلاسهای کوچکتر تقسیم کنید. اجازه دهید یک میکسین یک کار را انجام دهد و آن را به خوبی انجام دهد. در مثال قبلی، مدل میکسین مورد استفاده برای بهروزرسانی زمان *created* و *modified* را میتوان به راحتی فاکتور گرفت، همانطور که در کد زیر نشان داده شده است: ``` class TimeStampedModel(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now =True) class Meta: abstract = True class Postable(TimeStampedModel): message = models.TextField(max_length=500) ... class Meta: abstract = True class Post(Postable): ... class Comment(Postable): ... ``` ما الان دو کلاس پایه داریم. با این حال، عملکردها به وضوح از هم جدا شده است. میکسین را میتوان به عنوان یک ماژول جدا تعریف کرد و در اپهای دیگر دوباره استفاده کرد. # الگو — پروفایلهای کاربر **مشکل:** هر وب سایت مجموعه متفاوتی از جزئیات را در پروفایل کاربر ذخیره میکند. با این حال، مدل پیشساخته کاربر در جنگو، برای جزئیات احراز هویت در نظر گرفته شده است. **راه حل:** یک کلاس پروفایل کاربری با یک رابطه یک به یک با مدل کاربر ایجاد کنید. #### جزییات مشکل جنگو، یک مدل بسیار مناسب برای تعریف کردن کاربر، ارائه میدهد. شما میتوانید از آن در هنگام ایجاد یک کاربر super user یا ورود به رابط کاربری استفاده کنید. دارای چند فیلد اساسی مانند نام کامل، نام کاربری و ایمیل است. با این حال، اکثر پروژههای دنیای واقعی، اطلاعات بسیار بیشتری را در مورد کاربران، مانند آدرس، فیلمهای مورد علاقه یا تواناییهای ابرقدرت آنها نگه میدارند. از جنگو 1.5 به بعد، مدل کاربر پیش فرض را میتوان گسترش داد یا جایگزین کرد. با این حال، اسناد رسمی اکیداً توصیه میکنند که فقط دادههای احراز هویت را حتی در یک مدل کاربر سفارشی ذخیره کنید (این بخش مربوط به اپلیکیشن `auth` است). پروژههای خاص به چندین نوع کاربر نیاز دارند. به عنوان مثال، سوپربوک میتواند توسط ابرقهرمانان و غیر ابرقهرمانان استفاده شود. ممکن است فیلدهای مشترک و برخی فیلدهای متمایز بر اساس نوع کاربر وجود داشته باشد. #### جزییات راه حل راه حل رسمی توصیه شده، ایجاد یک مدل پروفایل کاربر است. این مدل باید با مدل کاربری شما رابطه یک به یک داشته باشد. تمام اطلاعات اضافی کاربر در این مدل ذخیره میشود: ``` class Profile(models.Model): user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True ) ``` توصیه میشود برای جلوگیری از مشکلات همزمانی در برخی از پایگاههای پشتیبان مانند PostgreSQL، مقدار `primary_key` را به طور واضح روی `True` تنظیم کنید. بقیه مدل میتواند شامل هر گونه جزئیات دیگر کاربر مانند تاریخ تولد، رنگ مورد علاقه و غیره باشد. هنگام طراحی مدل پروفایل، توصیه میشود که تمام فیلدهای جزئیات پروفایل باید *nullable* یا *حاوی مقادیر پیش فرض* باشند. به طور شهودی، ما میتوانیم درک کنیم که یک کاربر نمی تواند هنگام ثبت نام، تمام جزئیات نمایه خود را پر کند. علاوه بر این، ما اطمینان حاصل میکنیم که کنترل کننده سیگنال در هنگام ایجاد نمونه پروفایل، هیچ پارامتر اولیهای را پاس نمی کند. ###### سیگنالها در حالت ایده آل، هر بار که یک نمونه مدل کاربر ایجاد میشود، یک نمونه پروفایل کاربر مربوطه نیز باید ایجاد شود. اینکار معمولاً با استفاده از سیگنال انجام میشود. برای مثال، میتوانیم سیگنال `post_save` را از مدل کاربر، با استفاده از کنترلکننده سیگنال زیر در `profiles/signals.py` گوش کنیم: ``` from django.db.models.signals import post_save from django.dispatch import receiver from django.conf import settings from . import models @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_profile_handler(sender, instance, created, **kwargs): if not created: return # Create the profile object, only if it is newly created profile = models.Profile(user=instance) profile.save() ``` مدل `Profile` هیچ پارامتر اولیه اضافی به جز `user=instance` را ارسال نکرده است. قبلاً مکان خاصی برای مقداردهی اولیه کد سیگنال وجود نداشت. به طور معمول، آنها در `models.py` فراخوانی یا پیاده سازی میشدند (که قابل اعتماد نبود). با این حال، با ویژگی `app-loading refactor` در جنگو 1.7، مکان کدهای اولیه در برنامه به خوبی تعریف شده است. ابتدا، متد `ProfileConfig` را در فایل `apps.py` در اپ پروفایل تغییر دهید و درون متد `ready`، سیگنال را تعریف کنید: ``` # apps.py from django.apps import AppConfig class ProfilesConfig(AppConfig): name = "profiles" verbose_name = 'User Profiles' def ready(self): from . import signals ``` سپس در بخش `INSTALLED_APPS`، خطی که مسیر اپ را تعریف میکند به کمک آدرس دهی نقطهای به `AppConfig` متصل میکنیم. فایل تنظیمات به شکل زیر خواهد شد: ``` INSTALLED_APPS = [ 'profiles.apps.ProfilesConfig', 'posts', ... ``` با تنظیم سیگنالها، دسترسی به `user.profile` باید یک شی `Profile` را از طریق هر کاربر، حتی کاربران تازه ایجاد شده، برگرداند. ##### Admin اکنون، جزئیات یک کاربر در دو مکان مختلف در داخل ادمین خواهد بود: جزئیات احراز هویت در صفحه مدیریت معمولی کاربر، و جزئیات اضافی پروفایل همان کاربر در یک صفحه مدیریت نمایه جداگانه. این خیلی دست و پا گیر میشود. برای راحتی، ادمین پروفایل را میتوان با تعریف یک `UserAdmin` سفارشی در `profiles/admin.py`، به صورت زیر به ادمین پیش فرض کاربر، اضافه کرد: ``` from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import Profile from django.contrib.auth.models import User class UserProfileInline(admin.StackedInline): model = Profile class NewUserAdmin(UserAdmin): inlines = [UserProfileInline] admin.site.unregister(User) admin.site.register(User, NewUserAdmin) ``` # گونههای مختلف پروفایل فرض کنید به چندین نوع کاربر و پروفایلهای مربوط به آنها در برنامه خود نیاز دارید - باید یک فیلد برای ردیابی نوع پروفایل کاربر وجود داشته باشد. خود دادههای `profile` باید در مدلهای جداگانه یا یک مدل یکپارچه ذخیره شوند. یک رویکرد تجمیعی برای `Profile` توصیه میشود زیرا انعطاف پذیری برای تغییر انواع `Profile` بدون از دست دادن جزئیات آنها را میدهد و پیچیدگی را به حداقل میرساند. در این رویکرد، مدل `Profile` شامل یک ابرمجموعه از تمام فیلدها از همه انواع `Profile` است. برای مثال، SuperBook به یک پروفایل نوع ابرقهرمانی و یک پروفایل معمولی (غیر ابرقهرمانی) نیاز دارد. میتوان آن را با استفاده از یک مدل پروفایل یکپارچه به صورت زیر پیاده سازی کرد: ``` class BaseProfile(models.Model): USER_TYPES = ( (0, 'Ordinary'), (1, 'SuperHero'), ) user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True) user_type = models.IntegerField(max_length=1, null=True, choices=USER_TYPES) bio = models.CharField(max_length=200, blank=True, null=True) def __str__(self): return "{}: {:.20}". format(self.user, self.bio or "")] class Meta: abstract = True class SuperHeroProfile(models.Model): origin = models.CharField(max_length=100, blank=True, null=True) class Meta: abstract = True class OrdinaryProfile(models.Model): address = models.CharField(max_length=200, blank=True, null=True) class Meta: abstract = True class Profile(SuperHeroProfile, OrdinaryProfile, BaseProfile): pass ``` ما جزئیات پروفایل را در چندین کلاس پایه انتزاعی گروه بندی کردیم تا موضوعات را از هم جدا کنیم. کلاس `BaseProfile` شامل تمام جزئیات پروفایل رایج، صرف نظر از نوع کاربر است. همچنین دارای یک قسمت `user_type` است که پروفایل فعال کاربر را ردیابی میکند. کلاس `SuperHeroProfile` و کلاس `OrdinaryProfile` به ترتیب حاوی جزئیات `Profile` مخصوص کاربران ابرقهرمانی و غیرقهرمانی هستند. در نهایت، کلاس `Profile` از تمام این کلاسهای پایه برای ایجاد یک ابرمجموعه از جزئیات پروفایل مشتق میشود. برخی از جزئیاتی که در هنگام استفاده از این روش باید رعایت شود به شرح زیر است: - تمام فیلدهای `Profile` که متعلق به کلاس یا کلاسهای پایه انتزاعی آن هستند باید nullable یا دارای مقدار پیش فرض باشند. - این رویکرد ممکن است فضای پایگاه داده بیشتری را به ازای هر کاربر مصرف کند، اما انعطاف پذیری فوق العادهای میدهد. - فیلدهای فعال و غیرفعال برای نوع `Pofile` باید خارج از مدل مدیریت شوند. برای مثال، فرمی برای ویرایش نمایه باید فیلدهای مناسب را بر اساس نوع کاربر فعال فعلی نشان دهد. # Pattern – service objects **مشکل**: مدلها میتوانند بزرگ و غیرقابل مدیریت شوند. تست و نگهداری آنها سخت تر میشود زیرا یک مدل بیش از یک کار را انجام میدهد. **راهحل**: مجموعهای از متدهای مرتبط یا یک مدل را در یک شیء تخصصی خدماتی به نام *Service* جای دهید. #### جزئیات مشکل مدلهای چاق، ویوی لاغر ضربالمثلی است که معمولاً برای مبتدیان جنگو گفته میشود. در حالت ایده آل، ویوهای شما نباید حاوی چیزی غیر از منطق برنامه باشد. با این حال، با گذشت زمان، کدهایی که نمی توانند در جای دیگری قرار گیرند، تمایل پیدا میکنند درون مدلها قرار گیرند. به زودی، مدلها تبدیل به محل تخلیه کد میشوند. اگر مدل شما حاوی هر یک از موارد زیر است، یک شی *Service* برای آن نیاز دارد: 1. تعامل با سرویسهای خارجی، به عنوان مثال، بررسی اینکه آیا کاربر واجد شرایط دریافت پروفایل *SuperHeroProfile* هست یا نه، به کمک یک وبسرویس. 2. کارهای کمکی که با پایگاه داده سروکار ندارند، به عنوان مثال، ایجاد یک URL کوتاه یا کپچای تصادفی برای یک کاربر 3. ساختن یک شی با عمر کوتاه بدون نیاز به پایگاه داده، به عنوان مثال، ایجاد یک پاسخ JSON برای یک تماس AJAX 4. عملکردی که چندین نمونه مدل را در بر میگیرد اما به هیچکس تعلق ندارد 5. وظایف طولانی مدت مانند وظایف Celery مدلها در جنگو از الگوی Active Record پیروی میکنند، یعنی هر نمونه از کلاس، مربوط به یک ردیف در جدول پایگاه داده است. در حالت ایدهآل، آنها هم دسترسی به پایگاه داده و هم منطق برنامه (یا دامنه) را محصور میکنند. با این حال، منطق برنامه را در حداقل ممکن، نگه دارید. در حین آزمایش، اگر متوجه شدیم که پایگاه داده را حتی در حالی که از آن استفاده نمیکنیم، به کار میگیریم، باید کلاس مدل را تجزیه کنیم. استفاده از یک شیء Service در چنین شرایطی توصیه میشود. #### جزییات راه حل اشیاء سرویس **Plain Old Python Objects (POPO)** یا اشیاء ساده قدیمی پایتون، هستند که یک سرویس یا تعاملات با یک سیستم را محصور میکنند. آنها معمولاً در یک فایل جداگانه با نام *services.py* یا *utils.py* نگهداری میشوند. به عنوان مثال، بررسی یک وب سرویس گاهی اوقات در یک متد مدل به شرح زیر قرار میگیرد: ``` class Profile(models.Model): ... def is_superhero(self): url = "این حمله در مرورگرهای فعلی مانند آخرین کروم با شکست مواجه میشود، که پیام خطای زیر را در کنسول نشان میدهد: از اجرای اسکریپت جاوا اسکریپت خودداری کرد. . کد منبع اسکریپت در درخواست یافت شد.اگر نمیدانید که یک پیام هشدار ساده چه آسیبی میتواند داشته باشد، به یاد داشته باشید که هر کد جاوا اسکریپت را میتوان به همان شیوه اجرا کرد. در بدترین حالت، کوکی های کاربر را می توان با وارد کردن عبارت جستجوی زیر به سایتی که توسط مهاجم کنترل می شود ارسال کرد: ```js ``` پس از ارسال کوکیهای شما، مهاجم ممکن است بتواند حمله جدیتری انجام دهد. ### چرا کوکی های شما ارزشمند است؟ شاید ارزش درک این را داشته باشد که چرا کوکی ها هدف چندین حمله هستند. به زبان ساده، دسترسی به کوکیها به مهاجمان اجازه میدهد که شما را جعل کنند و حتی کنترل حساب وب شما را در دست بگیرند. برای درک دقیق این موضوع، باید مفهوم **sessions** را درک کنید.HTTP بدون تابعیت است این بدان معناست که هر درخواست HTTP که سرور دریافت میکند مستقل است و به درخواستهایی که قبل از آن ارائه شدهاند مربوط نمیشود. جنگو چه یک کاربر ناشناس یا یک کاربر تأیید شده باشد، با مدیریت جلسات، فعالیت های آنها را برای مدت زمان مشخصی پیگیری می کند. یک جلسه شامل شناسه جلسه در انتهای کلاینت، یعنی مرورگر و یک شی دیکشنری مانند است که در انتهای سرور ذخیره می شود. شناسه جلسه یک رشته تصادفی 32 نویسه ای است که به عنوان یک کوکی در مرورگر ذخیره می شود. هر بار که یک کاربر از یک وب سایت درخواستی می کند، تمام کوکی های او، از جمله این شناسه جلسه، همراه با درخواست ارسال می شود. در انتهای سرور، جنگو یک ذخیرهسازی جلسه دارد که این شناسه جلسه را به دادههای جلسه نگاشت میکند. به طور پیش فرض، جنگو داده های جلسه را در جدول پایگاه داده **django_session** ذخیره می کند. هنگامی که کاربر با موفقیت وارد سیستم می شود، جلسه متوجه می شود که احراز هویت موفقیت آمیز بوده و کاربر را پیگیری می کند. بنابراین، کوکی به یک تأیید هویت موقت کاربر برای تراکنشهای بعدی تبدیل میشود. هر کسی که این کوکی را بدست آورد می تواند از این برنامه وب به عنوان آن کاربر استفاده کند که به آن Session Hijacking می گویند. ### جنگو چگونه کمک میکند؟ شاید مشاهده کرده باشید که مثال من به دو دلیل روشی بسیار غیرمعمول برای پیاده سازی view در جنگو بود: از الگوها برای رندر استفاده نمی کرد و کلاس های فرم استفاده نمی شد. هر دوی آنها اقدامات پیشگیری XSS را دارند. بهطور پیشفرض، جنگو الگوهای فرار خودکار نویسههای ویژه HTML را ایجاد میکند. بنابراین، اگر رشته جستجو را در قالب نمایش داده بودید، همه تگ ها با کد HTML بودند. این کار تزریق اسکریپتها را غیرممکن میکند، مگر اینکه صریحاً با علامتگذاری محتوا بهعنوان امن، آنها را خاموش کنید. > استفاده از کلاسهای فرم در جنگو برای اعتبارسنجی و سالمسازی ورودی نیز یک اقدام متقابل بسیار مؤثر است. برای مثال، اگر برنامه شما به شناسه کارمند عددی نیاز دارد، از کلاس **IntegerField** به جای کلاس **CharField** مجاز تر استفاده کنید. در مثال ما، میتوانیم از یک کلاس **RegexValidator** در فیلد عبارت جستجوی خود استفاده کنیم تا کاربر را به کاراکترهای الفبایی محدود کنیم و اجازه دهیم نمادهای نقطهگذاری توسط ماژول جستجوی شما شناسایی شوند. محدوده قابل قبول ورودی کاربر را تا حد امکان محدود کنید. ### جایی که جنگو ممکن است کمکی نکند جنگو می تواند از طریق فرار خودکار در قالب ها از ۸۰ درصد حملات XSS جلوگیری کند. برای سناریوهای باقی مانده، باید مراقب باشید که وظایف زیر را انجام دهید: - Quote all HTML attributes, for example, replace `` with `` - فرار از داده های پویا در CSS یا جاوا اسکریپت با استفاده از روش های **سفارشی** - اعتبارسنجی همه URL ها، به ویژه در برابر پروتکل های ناامن مانند جاوا اسکریپت - اجتناب از XSS سمت کاربر (همچنین به عنوان XSS مبتنی بر DOM شناخته می شود) به عنوان یک قانون کلی در برابر XSS، من فیلتر در ورودی و معادل سازی خروجی(output escaping) را پیشنهاد میکنم. اطمینان حاصل کنید که هر دادهای را که وارد میشود کاملاً اعتبارسنجی و پاکسازی (فیلتر) شده باشد و بلافاصله قبل از ارسال آن به کاربر، آنها را تبدیل (output escaping) میکنید—مخصوصاً، اگر نیاز به پشتیبانی از ورودی کاربر با قالببندی HTML مانند نظرات دارید، از Markdown استفاده کنید.
فیلتر کردن ورودی ها و معادل سازی خروجی ها### جعل های درخواست بین سایتی(Cross-site request forgery) **جعل های درخواست بین سایتی (CSRF)** حمله ای است که کاربر را فریب می دهد تا در حالی که از سایت دیگری بازدید می کند، اقدامات ناخواسته ای را در یک وب سایت انجام دهد، جایی که قبلاً احراز هویت شده اند. مثلاً در یک فرم، یک مهاجم میتواند یک تگ IMG یا IFRAME را در صفحه قرار دهد که درخواستی را که به دقت طراحی شده است به سایت تأیید شده ارسال میکند. به عنوان مثال، تصویر جعلی0\*0 زیر را می توان در یک کامنت جاسازی کرد: ```html
**اتاق امن**
به محض اینکه استیو از اتاق هیئت مدیره خارج شد، تلفن خود را بیرون آورد و
یک ایمیل تک خطی واضح را به تیمش ارسال کرد: "این کار است!"
در 60 دقیقه اخر او توسط پرسش های جزعی رعیس درباره کوچک
ترین نکات اجرای برنامه به چالش کشیده شد.
خانم اُ، با ناراحتی استیو، در تمام مدت سکوت خود را حفظ کرد.
وارد کابینش شد و یک بار دیگر پرینت اسلایدهایش را باز کرد. پس از معرفی چک لیست ها،
. پس از معرفی چک لیست ها، تعداد باگ های بی اهمیت به شدت کاهش یافت. ویژگیهای اساسی که گنجاندن آنها
در نسخه غیرممکن بود از طریق همکاری اولیه با سرورهای
سرورهای مفیدی مانند Hexa و Aksel به کار گرفته شدند.
به لطف کمپین بازاریابی درخشان سو، تعداد ثبت نامها برای سایت بتا از 9000 گذشت.
استیو هرگز در دوران حرفهای خود این همه علاقه برای راه اندازی ندیده بود
آن موقع بود که متوجه چیز عجیبی در مورد روزنامه روی میزش شد.
پانزده دقیقه بعد، او با عجله از راهرو در طبقه 21 پایین آمد. در انتهای آن،
، دری با علامت 2109 وجود داشت. وقتی در را باز کرد، اوان را دید که
روی چیزی شبیه یک لپتاپ اسباببازی پلاستیکی سفید کار میکرد.
استیو پرسید: "چرا سرنخ های جدول کلمات متقاطع را حلقه زدی؟
می توانستی با من تماس بگیری."
«او با پوزخند پاسخ داد: می خواهم چیزی به شما نشان دهم». لپ تاپش را گرفت و بیرون رفت.
او بین اتاق 2110 و خروجی آتش متوقف شد. روی زانوهایش افتاد و با دست راست
کاغذ دیواری رنگ و رو رفته را گرفت. او زمزمه کرد: "اینجا باید یک قفل وجود داشته باشد."
سپس دستش ایستاد و دسته ای را که به سختی از دیوار بیرون زده بود چرخاند.
قسمتی از دیوار چرخید و متوقف شد. ورودی اتاقی را نشان داد که با چراغ قرمز
روشن شده بود. تابلویی در داخل که از پشت بام آویزان بود
روی آن نوشته شده بود: «اتاق امن »21B.
وقتی وارد شدند، صفحات و چراغهای متعددی به خودی خود روشن شدند.
یک صفحه نمایش بزرگ روی دیوار نوشته بود "احراز هویت لازم است. کلید را وارد کنید."
ایوان برای مدت کوتاهی این را تحسین کرد و شروع به سیم کشی لپ تاپ خود کرد.
ایوان، ما اینجا چه کار می کنیم؟" استیو با صدایی خاموش پرسید.
" ایوان ایستاد، "اوه، درست است. حدس میزنم تا پایان آزمایشها کمی وقت داریم."
او یک نفس عمیق کشید.
"به یاد دارید زمانی که خانم O از من خواست به پایگاه کد سنتینل نگاه کنم؟
من این کار را کردم. متوجه شدم که کد منبع سانسور شده به ما داده شده است.
منظورم این است که می توانم برخی از رمزهای عبور را اینجا و آنجا حذف کنم،
اما هزاران خط کد را درک کنم؟ مدام فکر می کردم - باید اتفاقی می افتاد."
بنابراین، با دسترسی من به بایگانی، برخی از نسخه های پشتیبان قدیمی را برداشتم.
" احتمال پاک نشدن یک رسانه مغناطیسی به طرز شگفت آوری زیاد است.
به هر حال، من می توانم بیشتر کدهای پاک شده را بازیابی کنم. آنچه را دیدم باور نخواهید کرد. "
Sentinel یک پروژه شبکه اجتماعی معمولی نبود.
این یک برنامه نظارتی بود. شاید بزرگترین شناخته شده برای بشر.
پس از جنگ سرد، گروهی از کشورها برای ایجاد شبکه ای
برای اشتراک گذاری اطلاعات اطلاعاتی به یکدیگر پیوستند. شبکه ای از انسان ها
و نگهبانان. انتینل ها کامپیوترهایی نیمه مستقل با قدرت محاسباتی باورنکردنی هستند.
برخی معتقدند که آنها کامپیوترهای کوانتومی هستند.
نگهبانها در هزاران مکان استراتژیک در سراسر بسترهای اقیانوسی جهان
که کابلهای اصلی فیبر نوری از آنجا عبور میکنند، قرار گرفتند.
آنها با انرژی زمین گرمایی کار میکردند، و عملاً غیرقابل تخریب بودند.
آنها تقریباً به تمام ارتباطات اینترنتی در اکثر کشورها دسترسی داشتند.
در مقطعی در دهه نود، شاید از ترس نظارت عمومی، برنامه سنتینل تعطیل شد.
اینجاست که واقعا جالب می شود. تاریخچه کد نشان می دهد که توسعه در Sentinels
توسط شخصی به نام Cerebos ادامه یافت. این کد به طرز چشمگیری از توانایی های نظارتی
خود برای ایجاد نوعی ابر رایانه موازی بسیار افزایش یافته است. یک جانور اعداد خرد کننده
که هیچ الگوریتم رمزگذاری برای او چالش مهمی ایجاد نمی کند.
نقض را به یاد دارید؟ برای من سخت بود که باور کنم قبل از آمدن ابرقهرمانان
حتی یک حرکت تهاجمی وجود نداشت. بنابراین، من کمی تحقیق کردم.
امنیت سایبری SHIM به صورت پنج حلقه متحدالمرکز طراحی شده است.
ما، کارمندان، در بیرونی ترین، کم برخوردارترین حلقه ای هستیم که توسط سائورون
محافظت می شود. حلقههای داخلی با الگوریتمهای رمزنگاری قویتر طراحی میشوند.
این اتاق در طبقه 4 است.
حدس من این است که مدتها قبل از اینکه ما از این رخنه مطلع شویم، همه
سیستمهای سائورون در معرض خطر قرار گرفته بودند. سیستمها از کار افتاده بودند
و ورود آن روباتها به محوطه دانشگاه عملاً یک راهپیمایی بود. من فقط به سیاهه ها نگاه کردم.
این حمله بسیار هدفمند بود – همه چیز از آدرس های IP گرفته
تا ورود به سیستم از قبل شناخته شده بود.
"داخلی?" استیو با وحشت پرسید.
بله. با این حال، Sentinels فقط برای سطح 5 نیاز به کمک داشت.
" هنگامی که آنها کلیدهای عمومی برای سطح 4 را به دست آوردند،
آنها شروع به حمله به سیستم های سطح 4 کردند. این دیوانه به نظر
می رسد اما این استراتژی آنها بود."
"چرا دیوانه است؟"
"خب، بیشتر امنیت آنلاین جهان مبتنی بر رمزنگاری با کلید عمومی یا رمزنگاری
نامتقارن است. این امنیت مبتنی بر دو کلید است: یکی عمومی و دیگری خصوصی.
اگرچه از نظر ریاضی مرتبط است، یافتن یک کلید در صورت داشتن
این کلید از نظر محاسباتی غیرعملی است. دیگر"
"آیا می گویید که شبکه سنتینل می تواند؟"
"در واقع، آنها می توانند برای کلیدهای کوچکتر. بر اساس آزمایشاتی که در حال حاضر
انجام می دهم، قدرت آنها به طور قابل توجهی افزایش یافته است.
با این سرعت، آنها باید در کمتر از 24 ساعت برای حمله دیگری آماده شوند."
"لعنتی، آن زمان است که SuperBook پخش می شود!"
### یک چک لیست امنیتی مفید
امنیت یک فکر بعدی نیست، بلکه در نحوه نوشتن برنامه ها ضروری است.
با این حال، از آنجایی که انسان هستید، داشتن یک چک لیست برای یادآوری
موارد مشترک مفید است.
نکات زیر حداقلی از بررسی های امنیتی است که باید قبل از عمومی کردن برنامه جنگو خود انجام دهید:
- **به داده های یک مرورگر، API یا هر منبع خارجی اعتماد نکنید:**
این یک قانون اساسی است. اطمینان حاصل کنید که هر گونه داده خارجی را تأیید و پاکسازی می کنید.
- **نگه ندارید** کلید خصوصی را **در کنترل نسخه:** به عنوان بهترین تمرین، انتخاب کنید **کلید خصوصی**
پکیج `django-environ` را ببینید.
- **رمزهای عبور را در متن ساده ذخیره نکنید:** در عوض هش رمز عبور برنامه خود را ذخیره کنید. یک نمک تصادفی نیز اضافه کنید.
- **هیچ داده حساسی را ثبت نکنید:** اطلاعات محرمانه مانند جزئیات کارت اعتباری یا کلیدهای API را قبل از ثبت آنها در فایل های گزارش خود فیلتر کنید.
- **هر تراکنش امن یا ورود به سیستم باید از SSL استفاده کند:** آگاه باشید که استراق سمع کنندگان در
همان شبکه ای که اگر در HTTPS نباشد، می توانید به ترافیک وب خود گوش دهید.
در حالت ایده آل، شما باید از HTTPS برای کل سایت استفاده کنید.
- **از استفاده از تغییر مسیر به URL های ارائه شده توسط کاربر خودداری کنید:** اگر ریدایرکت هایی مانند
http://example.com/r?url=http://evil.com, سپس همیشه دامنه های در لیست سفید را بررسی کنید.
- **بررسی مجوز حتی برای کاربران احراز هویت شده:** قبل از انجام هر کدام
تغییر با عوارض جانبی، بررسی کنید که آیا کاربر وارد شده مجاز به انجام آن است یا خیر.
- **از دقیق ترین عبارات منظم ممکن استفاده کنید:**
چه «URLconf» یا اعتبار سنجیهای فرم شما، باید از عبارات منظم تنبل و عمومی اجتناب کنید.
- **کد پایتون خود را در ریشه وب نگه ندارید:**
این می تواند منجر به نشت تصادفی کد منبع شود اگر به عنوان متن ساده ارائه شود.
- **به جای ساختن رشته ها با دست از الگوهای جنگو استفاده کنید:**
قالب ها در برابر حملات XSS محافظت می کنند.
- **از Django ORM به جای دستورات SQL استفاده کنید:**
ORM محافظت در برابر تزریق SQL را ارائه می دهد.
- **از فرم های جنگو با ورودی POST برای هر اقدامی با عوارض جانبی استفاده کنید:**
ممکن است استفاده از فرم ها برای یک دکمه ساده رای زیاده روی به نظر برسد، اما این کار را انجام دهید.
- **CSRF باید فعال و استفاده شود:**
اگر نماهای خاصی را با استفاده از دکوراتور @csrf_exempt معاف می کنید، بسیار مراقب باشید.
- **اطمینان حاصل کنید که جنگو و همه بسته ها آخرین نسخه هستند:**
برای به روز رسانی برنامه ریزی کنید. آنها ممکن است نیاز به
تغییراتی در کد منبع شما داشته باشند. با این حال، آنها ویژگیهای جدید
درخشان و اصلاحات امنیتی را نیز به ارمغان میآورند.
- **اندازه و نوع فایل های آپلود شده توسط کاربر را محدود کنید:**
بارگذاری فایل های اجرایی یا اسکریپت ها را رد کنید.
بارگذاری فایل های اجرایی یا اسکریپت ها را رد کنید.
- **یک برنامه پشتیبان و بازیابی داشته باشید:**
به لطف مورفی، می توانید برای یک حمله اجتناب ناپذیر،
فاجعه یا هر نوع خرابی دیگری برنامه ریزی کنید. اطمینان حاصل کنید که
برای به حداقل رساندن از دست دادن داده ها، به طور مکرر نسخه پشتیبان تهیه می کنید.
برخی از این موارد را می توان به طور خودکار با استفاده از Erik's Pony Checkup
در http://ponycheckup.com/ بررسی کرد. با این حال، توصیه می کنم
این چک لیست را پرینت یا کپی کنید و روی میز خود بچسبانید.
به یاد داشته باشید که این لیست به هیچ وجه جامع نیست و جایگزینی
برای ممیزی امنیتی مناسب توسط یک متخصص نیست.
### خلاصه
در این فصل، ما به انواع رایج حملاتی که بر وب سایت ها و برنامه های کاربردی
وب تأثیر می گذارند نگاه کردیم. در بسیاری از موارد، توضیح تکنیک ها برای
وضوح و به قیمت جزئیات ساده شده است. با این حال، هنگامی که ما شدت حمله را درک کنیم،
می توانیم از اقدامات متقابلی که جنگو ارائه می دهد قدردانی کنیم.
در فصل پایانی خود، نگاهی به فعالیت های پیش از استقرار با جزئیات بیشتر
خواهیم داشت. ما همچنین نگاهی به استراتژی های مختلف استقرار، مانند
میزبانی مبتنی بر ابر برای استقرار یک برنامه جنگو خواهیم داشت.
================================================
FILE: 13-Production-Ready/README.md
================================================
# آماده برای تولید
در این فصل به مباحث زیر می پردازیم:
- انتخاب یک وب استک
- رویکردهای میزبانی
- بزارهای استقرار
- مانیتورینگ
- نکاتی برای کارایی
خوب شما تاکنون یک برنامه وب کاملا کاربردی را در جنگو توسعه داده و آنرا مورد آزمایش قرار داده اید. استقرار این برنامه میتواند شامل مجموعهای از فعالیتها از انتخاب ارائهدهنده میزبانی شما تا اجرای نصب باشد. حتی چالشبرانگیزتر میتواند اقدامات مربوط به حفظ یک سایت تولید شده باشد، تا بدون وقفه و مدیریت انفجارهای غیرمنتظره در ترافیک بالا کار کند.
قوانین مدیریت سیستم بسیار گسترده است. از این رو، این فصل زمینه های زیادی را پوشش خواهد داد. با این حال، با توجه به فضای محدود، سعی می کنیم شما را با جنبه های مختلف ساخت یک محیط تولید و پروداکشن آشنا کنیم.
### محیط تولید و پروداکشن
اگرچه بسیاری از ما به طور شهودی درک می کنیم که یک محیط تولید چیست، مشخص نمودن معنای واقعی آن حائز اهمیت است. محیط تولید به سادگی محیطی است که کاربران نهایی از برنامه شما استفاده می کنند. باید در دسترس، انعطاف پذیر، ایمن، پاسخگو باشد و باید ظرفیت فراوانی برای نیازهای فعلی (و آینده) داشته باشد.
بر خلاف یک محیط توسعه، احتمال آسیب واقعی کسب و کار به دلیل هر گونه مسائل در یک محیط تولید بالا است. از این رو، قبل از حرکت به سمت تولید، کد به محیطهای مختلف آزمایش و پذیرش منتقل میشود تا تا حد امکان از شر اشکالات خلاص شود. برای ردیابی آسان، هر تغییری که در محیط تولید ایجاد میشود باید ردیابی، مستند شده و برای همه اعضای تیم قابل دسترسی باشد.
در نتیجه، هیچ توسعه ای نباید به طور مستقیم در محیط تولید انجام شود. در واقع نیازی به نصب ابزارهای توسعه مانند کامپایلر یا دیباگر در محیط تولید نیست. وجود هر نرم افزار غیر ضروری سطح حمله سایت شما را افزایش می دهد و می تواند خطر امنیتی ایجاد کند.
اکثر برنامههای کاربردی وب در سایتهایی با خرابی بسیار کم مستقر میشوند، به عنوان مثال، مراکز داده بزرگ در پنج 9، یعنی 99.999 درصد، آپتایم هستند. با طراحی برای خرابی، حتی اگر یک جزء داخلی خراب شود، افزونگی کافی برای جلوگیری از خرابی کل سیستم وجود دارد. مفهوم اجتناب از یک نقطه شکست (SPOF) را می توان در هر سطح، سخت افزار یا نرم افزار اعمال کرد.
این امر درواقع مجموعه ای مهم از نرم افزارهایی است که شما انتخاب می کنید تا در محیط تولید خود اجرا شوند.
### انتخاب یک پشته وب(استک)
تا کنون، ما در مورد استک یا پشته ای که برنامه شما روی آن اجرا می شود صحبت نکرده ایم. حتی اگر در انتهای این کتاب در مورد آن صحبت می کنیم، بهتر است چنین تصمیماتی را به مراحل بعدی چرخه حیات برنامه موکول نکنید. در حالت ایدهآل، محیط توسعه شما باید تا حد امکان به محیط تولید نزدیک باشد تا از این جمله که می گوید اما در ماشین من کار میکند، جلوگیری شود.
با یک پشته وب، به مجموعه فناوری هایی اشاره می کنیم که برای ساخت یک برنامه وب استفاده می شوند. معمولاً به صورت مجموعهای از مؤلفهها، مانند سیستم عامل، پایگاه داده و وب سرور، که همگی روی یکدیگر جمع شدهاند، نشان داده میشود. از این رو، از آن به عنوان پشته یاد می شود.
ما در اینجا عمدتاً روی راه حل های منبع باز تمرکز خواهیم کرد زیرا آنها به طور گسترده استفاده می شوند. با این حال، برنامه های تجاری مختلف نیز در صورتی که بیشتر با نیازهای شما مطابقت داشته باشند، می توانند مورد استفاده قرار گیرند.
### کامپوننت های یک پشته
یک پشته وب جنگو با استفاده از چندین نوع برنامه (یا لایه ها، بسته به اصطلاح شما) ساخته می شود. هنگام ساخت پشته وب خود، برخی از انتخاب هایی که ممکن است لازم باشد به شرح زیر است:
- کدام سیستم عامل و توزیع؟ به عنوان مثال، دبیان، رد هت یا OpenBSD
- کدام سرور WSGI؟ به عنوان مثال، Gunicorn یا uWSGI.
- کدام وب سرور؟ به عنوان مثال، Apache یا Nginx.
- کدام دیتابیس؟ به عنوان مثال، PostgreSQL، MySQL یا Redis
- کدام سیستم کش؟ مثلا Memcached یا Redis.
- کدام سیستم کنترل فرآیند و مانیتورینگ؟ به عنوان مثال، Upstart، Systemd، یا Supervisord.
- چگونه رسانه های استاتیک را ذخیره کنیم؟ به عنوان مثال، Amazon S3 یا CloudFront
ممکن است چندین مورد دیگر وجود داشته باشد، و این انتخاب ها نیز متقابلاً منحصر به فرد نیستند. برخی از چندین مورد از این برنامه ها به صورت پشت سر هم استفاده می شوند. به عنوان مثال، در دسترس بودن نام کاربری ممکن است در Redis جستجو شود، در حالی که پایگاه داده اولیه ممکن است PostgreSQL باشد.
وقتی نوبت به انتخاب پشته شما می رسد، هیچ پاسخی برای همه وجود ندارد. اجزای مختلف نقاط قوت و ضعف متفاوتی دارند. آنها را تنها پس از بررسی دقیق و آزمایش انتخاب کنید. به عنوان مثال، ممکن است شنیده باشید که Nginx یک انتخاب محبوب برای وب سرور است، اما ممکن است در واقع به اکوسیستم غنی ماژول ها یا گزینه های آپاچی نیاز داشته باشید.
گاهی اوقات، انتخاب پشته بر اساس دلایل مختلف غیر فنی است. سازمان شما ممکن است روی یک سیستم عامل خاص مانند دبیان برای همه سرورهایش استاندارد شده باشد، یا ارائه دهنده هاست ابری شما ممکن است تنها مجموعه محدودی از پشته ها را پشتیبانی کند.
از این رو، نحوه انتخاب میزبانی برنامه جنگو یکی از عوامل کلیدی در تعیین تنظیمات تولید شما است.
### ماشینهای مجازی یا داکر
بسیاری از ما به استفاده از ماشین های مجازی چه در توسعه و چه در تولید آشنا هستیم. این ابزارها برنامه شما (ماشین مهمان) را از زیرساخت اصلی (ماشین میزبان) جدا می کنند. فناوریهای کانتینری مانند Docker به طور فزایندهای برای استقرار ابری، یا مکمل یا جایگزین ماشینهای مجازی استفاده میشوند.
کانتینرها ابزاری برای ایجاد چندین نمونه فضای کاربر بر روی یک هسته هستند. برخلاف ماشینهای مجازی، کانتینرها از نیاز به راهاندازی اجتناب میکنند و سیستمعاملهای مهمان مجزا را اجرا میکنند. به طور معمول، هر کانتینر یک برنامه کاربردی و وابستگی های آن را در یک نمونه فضای کاربری جدا از سایر کانتینرها بسته بندی می کند. برخلاف ماشینهای مجازی، داکر نمونه جداگانهای از سیستم عامل ندارد، که باعث میشود سبکتر و سریعتر شروع یا متوقف شود.
داکر با اکوسیستم بزرگ و پشتیبانی گسترده در میان فروشندگان ابری، به فناوری انتخابی کانتینری تبدیل شده است. داکر ایمیج ها از یک ایمیج باینری به نام ایمیج پایه ایجاد می شوند یا به طور خودکار از یک اسکریپت به نام Dockerfile ساخته می شوند. این به شما کمک می کند تا همان محیط را در تولید برای اهداف توسعه یا آزمایش دوباره ایجاد کنید، بنابراین بهانه اما در دستگاه من کار کرد را پایان دهید.
### میکروسرویس ها
رایج ترین الگوی طراحی با استفاده از Docker، تجزیه برنامه ها و سرویس ها به میکروسرویس ها است. مزیت این است که میکروسرویسهای فردی میتوانند به طور مستقل توسعه یافته و به کار گرفته شوند، در حالی که در موقعیتهای سخت انعطافپذیرتر هستند. از این رو، فنآوریهای کانتینریسازی مانند Docker به دلیل حداقل سطح سربار و ایزوله در سطح کاربرد، یک تناسب طبیعی است.
مثال زیر یک مثال ساده از یک برنامه وب جنگو است که به عنوان میکروسرویس با استفاده از کانتینرها اجرا شده است:

این میکروسرویس واحد از سه کانتینر با اجزای منطقی مجزا تشکیل شده است: ظرف Nginx (وب سرور)، کانتینر Gunicorn/Django (برنامه وب) و کانتینر PostgreSQL (پایگاه داده). هر ظرف از یک داکر ایمیج که ممکن است با استفاده از یک Dockerfile ساخته شود، نمونه سازی شده است.
کانتینرهای Docker یک سیستم فایل زودگذر دارند، بنابراین دادههای پایدار با ایجاد صریح یک حجم مدیریت میشوند. از ولوم ها می توان برای اشتراک گذاری داده ها بین کانتینرها استفاده کرد. در این حالت، فایلهای استاتیک پروژه جنگو را میتوان در کانتینر Nginx به اشتراک گذاشت تا مستقیماً به آنها سرویس داده شود.
همانطور که می توانید تصور کنید، اکثر برنامه های کاربردی دنیای واقعی از چندین Microservice تشکیل شده اند و هر یک از آنها به چندین کانتینر نیاز دارند. اگر آنها را روی چندین سرور اجرا کنید، چگونه این کانتینرها را در آنها مستقر خواهید کرد؟ چگونه میتوانید میکروسرویسهای فردی را به سمت بالا یا پایین مقیاس کنید؟ Kubernetes گسترده ترین راه حل توصیه شده برای مدیریت چنین خوشه های کانتینری است.
اگرچه ما در این بخش کانتینرها را در سطح بسیار بالایی پوشش دادهایم، اما جزئیات پیادهسازی زیادی مانند الگوهای استقرار وجود دارد که در اینجا نمیتوان به آنها پرداخت، زیرا میتوانند به تنهایی یک کتاب باشند. کانتینرها و ابزارهای ارکستراسیون با ایجاد آسانتر مدیریت محیطهای برنامه به بخش مهمی از توسعه برنامههای کاربردی وب مدرن تبدیل شدهاند.
### میزبانی و هاستینگ
وقتی نوبت به هاستینگ می رسد، باید مطمئن شوید که آیا به دنبال بستر(پلتفرم) میزبانی مانند Heroku هستید یا خیر. اگر اطلاعات زیادی در مورد مدیریت سرور ندارید یا کسی با آن دانش در تیم خود ندارید، پلتفرم میزبانی گزینه مناسبی است.
### پلتفرم به عنوان سرویس
**پلتفرم به عنوان سرویس** (PaaS) یک سرویس ابری است که در آن راه حل از قبل برای شما ارائه و مدیریت شده است. پلتفرم های محبوب برای میزبانی جنگو عبارتند از Heroku، PythonAnywhere و Google App Engine.
در بیشتر موارد، استقرار یک برنامه جنگو باید به سادگی انتخاب سرویسها یا اجزای پشته و خارج کردن کد منبع شما باشد. نیازی نیست خودتان هیچ گونه مدیریت یا راه اندازی سیستمی انجام دهید. پلتفرم به طور کامل مدیریت می شود.
مانند بسیاری از سرویس های ابری، زیرساخت ها نیز می توانند بر اساس تقاضا مقیاس شوند. اگر به پایگاه داده یا رم بیشتر روی یک سرور نیاز دارید، می توان آن را به راحتی از یک رابط وب یا خط فرمان تهیه کنید. قیمت گذاری در درجه اول بر اساس استفاده شما است.
نکته اصلی در مورد چنین پلتفرم های میزبانی این است که راه اندازی آنها بسیار آسان است و برای پروژه های کوچکتر ایده آل هستند. با افزایش تعداد کاربران، گران تر می شوند.
نکته منفی دیگر این است که برنامه شما ممکن است به یک پلتفرم گره بخورد یا پورت کردن آن دشوار شود. به عنوان مثال، Google App Engine فقط برای پشتیبانی از یک پایگاه داده غیررابطه ای استفاده می شود، به این معنی که شما باید از django-nonrel، یک فورکی(کپی) از جنگو، استفاده کنید. این محدودیت اکنون با Google Cloud SQL تا حدودی کاهش یافته است.
### سرورهای مجازی اختصاصی
سرور خصوصی مجازی (VPS) یک ماشین مجازی است که در یک محیط مشترک میزبانی می شود. از دیدگاه توسعهدهنده، به نظر میرسد یک ماشین اختصاصی (از این رو، کلمه خصوصی) با یک سیستم عامل از قبل بارگذاری شده است. شما باید خودتان کل پشته را نصب و راه اندازی کنید، اگرچه بسیاری از ارائه دهندگان VPS مانند WebFaction و DigitalOcean تنظیمات جنگو را آسان تر ارائه می دهند.
اگر مبتدی هستید و می توانید کمی وقت بگذارید، این روش را به شدت توصیه می کنم. به شما دسترسی ریشه (روت) داده می شود و می توانید کل پشته را خودتان بسازید. شما نه تنها متوجه خواهید شد که چگونه قطعات مختلف پشته به هم می رسند، بلکه کنترل کاملی در تنظیم دقیق هر جزء خواهید داشت.
در مقایسه با PaaS، VPS ممکن است ارزش بیشتری دربرابر پول پرداختی داشته باشد، به خصوص برای سایت های پربازدید. ممکن است بتوانید چندین سایت از یک سرور را نیز اجرا کنید.
### سرورلس
تصور کنید که نیاز به میزبانی سرویسی دارید که به ندرت استفاده می شود، اما پرداخت هزینه برای یک سرور اختصاصی که همیشه در حال اجرا است، هزینه بر یا ناکارآمد از نظر نگهداری است. به نظر میرسد در این حالت معماری های بدون سرور همان چیزی باشد که شما به دنبال آن هستید. نام بدون سرور یک نام اشتباه است زیرا تمام درخواستهای مشتری در واقع توسط سرورهایی انجام میشوند که به صورت پویا برای طول عمر درخواست ارائه میشوند.
اصطلاح مناسبتر Function as a Service (FaaS) است، زیرا این پلتفرمها از اجرای یک منطق برنامه مانند یک تابع کوچک پایتون پشتیبانی میکنند اما هیچ حالتی را ذخیره نمیکنند. ساخت یک برنامه کاربردی متشکل از چنین توابعی کاملاً شبیه به معماری میکروسرویس است که قبلاً مورد بحث قرار گرفت.
به طور معمول، شما فقط برای میلی ثانیه زمان سروری که یک برنامه بدون سرور استفاده می کند، پرداخت می کنید، که آن را بسیار ارزان تر از سرورهای اختصاصی می کند. مقیاسبندی بهطور خودکار انجام میشود، بنابراین هیچ تلاش اضافی برای رسیدگی به جهشهای عظیم در ترافیک لازم نیست. نکته مهم دیگر اینکه هیچ دردسر راه اندازی و نگهداری زیرساخت سرور هم وجود ندارد.
جنگو ممکن است به نظر در چنین محیطی کار نکند، اما Zappa استقرار برنامه های جنگو (در واقع، هر برنامه سازگار با WSGI) را بر روی یک پلتفرم بدون سرور مانند AWS Lambda با حداقل تغییرات آسان می کند. این امکان لذت بردن از تمام مزایای بدون سرور را در هنگام استفاده از جنگو باز می کند.
### رویکردهای دیگر برای هاستینگ
اگرچه میزبانی بر روی یک پلتفرم یا VPS دو گزینه محبوب میزبانی هستند، گزینه های زیاد دیگری نیز وجود دارد. اگر به افزایش کارایی علاقه دارید، می توانید یک سرور فیزیکی (bare metal) با هماهنگی از ارائه دهندگان، مانند Rackspace انتخاب کنید.
در انتهای سبکتر طیف میزبانی، میتوانید با میزبانی چندین برنامه در کانتینرهای Docker در هزینه صرفهجویی کنید. داکر ابزاری برای بسته بندی برنامه ها و وابستگی های شما در یک کانتینر مجازی است. در مقایسه با ماشینهای مجازی سنتی، کانتینر Docker سریعتر راهاندازی میشود و دارای کمترین میزان هزینههای سربار است (زیرا سیستم عامل یا هایپروایزر همراهی وجود ندارد).
داکر برای میزبانی برنامه های برپایه میکروسرویس ایده آل است. تقریباً هر ارائه دهنده PaaS و VPS از آنها پشتیبانی می کند و در همه جا در حال فراگیر شدن است.
همچنین یک پلتفرم توسعه عالی است زیرا کانتینرهای داکر کل حالت برنامه را در خود محصور می کنند و می توانند مستقیماً در تولید دیپلوی و مستقر شوند.
### ابزارهای استقرار سازی و دیپلوی
هنگامی که راه حل میزبانی خود را به صفر رساندید، ممکن است چندین مرحله در فرآیند استقرار شما وجود داشته باشد، از اجرای تست های رگرسیون گرفته تا ایجاد خدمات پس زمینه.
کلید یک فرآیند استقرار موفق، اتوماسیون است. از آنجایی که استقرار برنامه ها شامل یک سری مراحل کاملاً تعریف شده است، می توان به درستی به عنوان یک مشکل برنامه نویسی به آن نگاه کرد. هنگامی که یک استقرار اتوماسیون شده دارید، از ترس از دست دادن یک مرحله، لازم نیست نگران استقرار باشید.
در واقع، استقرار باید بدون درد و به همان اندازه که لازم است انجام شود. به عنوان مثال، تیم فیس بوک می تواند چندین بار در روز کد را برای تولید منتشر کند. با در نظر گرفتن پایگاه عظیم کاربر و پایگاه کد فیس بوک، این یک شاهکار چشمگیر است، با این حال، ضروری است زیرا رفع اشکالات و وصله های اضطراری باید در اسرع وقت اجرا شوند.
یک فرآیند استقرار خوب نیز ناتوان است. به عبارت دیگر، حتی اگر به طور تصادفی ابزار استقرار را دو بار اجرا کنید، اقدامات نباید دو بار اجرا شوند (یا بهتر است بگوییم باید آن را در همان حالت رها کنید).
بیایید نگاهی به برخی از ابزارهای محبوب برای استقرار برنامه های جنگو بیندازیم.
### Fabric
این مورد به دلیل سادگی و سهولت استفاده در بین توسعه دهندگان وب پایتون مورد علاقه است. فایلی به نام fabfile.py را در نظر دارد که تمام اقدامات (برای استقرار یا غیره) در پروژه شما را تعریف میکند. هر یک از این اقدامات می تواند یک shell command محلی یا راه دور باشد. میزبان راه دور از طریق SSH متصل می شود.
نقطه قوت اصلی Fabric توانایی آن در اجرای دستورات روی مجموعه ای از میزبان های راه دور است. به عنوان مثال، می توانید یک گروه **وب**را تعریف کنید که شامل نام میزبان همه وب سرورهای در حال تولید است.
**نکته:** با تعیین نام گروه وب در خط فرمان، میتوانید یک اکشن Fabric را فقط در برابر این سرورهای وب اجرا کنید.
برای نشان دادن وظایف مربوط به استقرار یک سایت با استفاده از Fabric، اجازه دهید نگاهی به یک سناریوی استقرار معمولی بیندازیم.
### گام های ساده برای استقرار
تصور کنید که یک برنامه وب با اندازه متوسط دارید که بر روی یک وب سرور واحد مستقر شده است. Git به عنوان ابزار کنترل نسخه و همکاری انتخاب شده است. یک مخزن مرکزی که با همه کاربران به اشتراک گذاشته شده است به شکل درخت Git برهنه ایجاد شده است.
فرض کنید سرور تولید شما به طور کامل راه اندازی شده است. هنگامی که فرمان استقرار Fabric خود را اجرا می کنید، مثلاً fab deploy، دنباله اسکریپت زیر از اقدامات انجام می شود:
1. تمام تست ها را به صورت محلی اجرا می کند
2. تمام تغییرات محلی Git را انجام می دهد
3. به یک مخزن مرکزی راه دور Git فشار می آورد
4. در صورت وجود، تضادهای ادغام را حل می کند
5. فایل های ثابت (CSS، تصاویر) را جمع آوری می کند.
6. فایل های استاتیک را در سرور فایل استاتیک کپی می کند
7. در میزبان راه دور، تغییرات را از یک مخزن مرکزی Git می کشد
8. در میزبان راه دور، مهاجرت (پایگاه داده) را اجرا می کند
9. در میزبان راه دور، app.wsgi را برای راه اندازی مجدد سرور WSGI لمس کنید
کل فرآیند به صورت خودکار است و باید در چند ثانیه تکمیل شود. به طور پیش فرض، اگر هر مرحله ای با شکست مواجه شود، استقرار متوقف می شود. اگرچه به صراحت ذکر نشده است، اما بررسی هایی برای اطمینان از عدم توانمندی فرآیند وجود دارد.
Fabric هنوز با پایتون 3 سازگار نیست، اگرچه توسعه دهندگان در حال انتقال آن هستند. در عین حال، میتوانید Fabric را در محیط مجازی Python 2.x اجرا کنید یا ابزارهای مشابهی مانند PyInvoke را بررسی کنید.
### مدیریت پیکره بندی ها
مدیریت چندین سرور در حالت های مختلف می تواند با Fabric سخت باشد. ابزارهای مدیریت پیکربندی مانند Chef، Puppet یا Ansible سعی می کنند یک سرور را به وضعیت مطلوبی برسانند.
بر خلاف Fabric، که نیاز به تعیین فرآیند استقرار به شیوه ای ضروری دارد، این ابزارهای مدیریت پیکربندی بیانی هستند. شما فقط باید وضعیت نهایی را که می خواهید سرور در آن قرار داشته باشد، مشخص کنید و نحوه رسیدن به آنجا را مشخص می کند.
برای مثال، اگر میخواهید مطمئن شوید که سرویس Nginx در هنگام راهاندازی در تمام سرورهای وب شما اجرا میشود، باید وضعیت سروری را تعریف کنید که سرویس Nginx هم در حال اجرا و هم در هنگام راهاندازی است. از طرف دیگر، با Fabric، باید مراحل دقیق نصب و پیکربندی Nginx را برای رسیدن به چنین حالتی مشخص کنید.
یکی از مهمترین مزایای ابزارهای مدیریت پیکربندی این است که به طور پیش فرض فاقد قدرت هستند. سرورهای شما می توانند از یک حالت ناشناخته به یک وضعیت شناخته شده بروند و در نتیجه مدیریت پیکربندی سرور آسان تر و استقرار قابل اعتماد را به همراه داشته باشند.
در میان ابزارهای مدیریت پیکربندی، Chef و Puppet از محبوبیت زیادی برخوردار هستند زیرا یکی از اولین ابزارها در این دسته بودند. با این حال، ریشه آنها در Ruby می تواند آنها را برای برنامه نویس پایتون کمی ناآشنا نشان دهد. برای چنین افرادی، ما Salt و Ansible را به عنوان جایگزین های عالی داریم.
ابزارهای مدیریت پیکربندی در مقایسه با ابزارهای ساده تر، مانند Fabric، منحنی یادگیری قابل توجهی دارند. با این حال، آنها ابزار ضروری برای ایجاد محیط های تولید قابل اعتماد هستند و مطمئنا ارزش یادگیری را دارند.
### مانیتورینگ
حتی یک وب سایت با اندازه متوسط می تواند بسیار پیچیده باشد. جنگو ممکن است یکی از صدها برنامه و سرویسی باشد که در حال اجرا و تعامل با یکدیگر هستند. همانطور که ضربان قلب و سایر علائم حیاتی را می توان به طور مداوم برای ارزیابی سلامت بدن انسان کنترل کرد، معیارهای مختلفی نیز در اکثر سیستم های تولیدی جمع آوری، تجزیه و تحلیل و ارائه می شوند.
در حالی که ثبت رویدادهای مختلف مانند ورود یک درخواست وب یا یک استثنا را پیگیری می کند، نظارت معمولاً به جمع آوری اطلاعات کلیدی به صورت دوره ای مانند استفاده از حافظه یا تأخیر شبکه اشاره دارد. با این حال، تفاوت ها در سطح برنامه محو می شوند، به عنوان مثال، هنگام نظارت بر عملکرد پرس و جو پایگاه داده، که ممکن است به خوبی از گزارش ها جمع آوری شود.
نظارت همچنین به تشخیص زودهنگام مشکلات کمک می کند. الگوهای غیرمعمول، مانند سنبله ها یا افزایش تدریجی بار، می تواند نشانه ای از مشکلات اساسی بزرگتر مانند نشت حافظه باشد. یک سیستم مانیتورینگ خوب می تواند صاحبان سایت را از مشکلات قبل از وقوع آنها آگاه کند.
ابزارهای مانیتورینگ معمولاً به یک سرویس پشتیبان (گاهی اوقات به نام عوامل) برای جمع آوری آمار و سرویس ظاهری برای نمایش داشبوردها یا تولید گزارش نیاز دارند. پشتیبان های محبوب جمع آوری داده ها عبارتند از StatsD و Monit. این داده ها را می توان به ابزارهای frontend مانند Graphite منتقل کرد.
چندین ابزار مانیتورینگ میزبان مانند New Relic و Status.io وجود دارد که راهاندازی و استفاده از آنها آسانتر است.
اندازه گیری عملکرد یکی دیگر از نقش های مهم نظارت است. همانطور که به زودی در بخش بعدی خواهیم دید، هر بهینه سازی پیشنهادی باید قبل از اجرا به دقت اندازه گیری و نظارت شود.
### بهبود کارایی
عملکرد یک ویژگی است. مطالعات نشان میدهد که سایتهای کند چگونه تأثیر نامطلوبی بر کاربران و در نتیجه درآمد دارند. به عنوان مثال آزمایش هایی در آمازون در سال 2007 نشان داد که به ازای هر 100 میلی ثانیه افزایش زمان بارگذاری [amazon.com](https://www.amazon.com/) فروش 1 درصد کاهش می یابد.
با اطمینان، چندین برنامه وب با کارایی بالا مانند Disqus و Instagram بر روی جنگو ساخته شده اند. در Disqus، در سال 2013، آنها میتوانستند 1.5 میلیون کاربر متصل همزمان، 45000 اتصال جدید در ثانیه، 165000 پیام در ثانیه را با تأخیر سرتاسر کمتر از 0.2 ثانیه مدیریت کنند.
کلید بهبود عملکرد، یافتن تنگناهاست. به جای تکیه بر حدس و گمان، همیشه توصیه می شود که برنامه خود را اندازه گیری و نمایه کنید تا این گلوگاه های عملکرد را شناسایی کنید. همانطور که لرد کلوین می گوید:
- "اگر نتوانید آن را اندازه گیری کنید، نمی توانید آن را بهبود ببخشید"
در بیشتر برنامههای کاربردی وب، گلوگاهها احتمالاً در انتهای مرورگر یا پایگاه داده به جای جنگو هستند. با این حال، برای کاربر، کل برنامه باید پاسخگو باشد.
بیایید به برخی از راه های بهبود عملکرد یک برنامه جنگو نگاهی بیندازیم. به دلیل تکنیکهای بسیار متفاوت، نکات به دو بخش تقسیم میشوند: قسمت جلویی و پشتیبان.
### کارایی سمت فرانت
برنامه نویسان جنگو ممکن است عملکرد frontend را نادیده بگیرند زیرا با درک نحوه عملکرد سمت کلاینت، معمولاً یک مرورگر، سروکار دارد. با این حال، بیایید از مطالعه استیو سادرز در مورد 10 وب سایت برتر رتبه بندی الکسا نقل قول کنیم:
- "80 تا 90 درصد از زمان پاسخدهی کاربر نهایی در قسمت فرانت صرف میشود. از آنجا شروع کنید."
یک نقطه شروع خوب برای بهینه سازی frontend این است که سایت خود را با سرعت صفحه گوگل یا یاهو بررسی کنید! YSlow (معمولاً به عنوان پلاگین مرورگر استفاده می شود). این ابزارها سایت شما را رتبه بندی می کنند و بهترین روش ها را توصیه می کنند، مانند به حداقل رساندن تعداد درخواست های HTTP یا gzip نمودن محتوا.
به عنوان بهترین روش، دارایی های استاتیک شما، مانند تصاویر، شیوه نامه ها و فایل های جاوا اسکریپت، نباید از طریق جنگو ارائه شوند. به جای یک فایل سرور استاتیک و ثابت، فضای ذخیره سازی ابری مانند آمازون S3 یا یک شبکه **تحویل محتوا** (CDN) باید برای عملکرد بهتر مورد استفاده قرار گیرد.
حتی در این صورت، جنگو میتواند به چندین روش به شما در بهبود عملکرد frontend کمک کند:
- کش بی نهایت با CachedStaticFilesStorage: سریع ترین راه برای بارگیری assets ایستا، استفاده از حافظه پنهان مرورگر است. با تنظیم زمان کش طولانی، می توانید از بارگیری مجدد همان دارایی دوباره و دوباره خودداری کنید. با این حال، چالش این است که بدانیم چه زمانی از حافظه پنهان هنگام تغییر محتوا استفاده نکنیم.
- کلاس CachedStaticFilesStorage این مشکل را با افزودن هش MD5 asset به نام فایل حل می کند. به این ترتیب می توانید TTL کش را برای این فایل ها بی نهایت افزایش دهید.
- برای استفاده از این، تنظیم CACHES با نام staticfiles را روی CachedStaticFilesStorage تنظیم کنید یا اگر فضای ذخیره سازی سفارشی دارید، از CachedFilesMixin ارث بری نمایید. همچنین، بهتر است کش های خود را به گونه ای پیکربندی کنید که از پشتیبان کش حافظه محلی برای انجام نام فایل استاتیک در جستجوی نام هش شده آن استفاده کند.
- از یک asset manager ایستا استفاده کنید: یک asset manager می تواند دارایی های استاتیک شما را از قبل پردازش کند تا آنها را کوچک کند، فشرده یا به هم متصل کند، در نتیجه اندازه آنها را کاهش داده و درخواست ها را به حداقل برساند. همچنین میتواند آنها را از قبل پردازش کند و به شما امکان میدهد آنها را به زبانهای دیگر بنویسید، مانند CoffeeScript و stylesheets از لحاظ نحوی عالی (Sass). چندین بسته جنگو وجود دارد که asset manager ثابت مانند django-pipeline یا websets را ارائه می دهد.
### کارایی سمت بک اند
دامنه کارایی سمت Backend تمامی وب استک سمت سرور شما را شامل می شود، از جمله پرس و جوهای پایگاه داده، رندر قالب، ذخیره سازی و کارهایی که در پس زمینه انجام می شوند. ممکن است بالاترین عملکرد را از آنها استخراج کنید زیرا کاملاً در کنترل شما است.
برای نیازهای پروفایل سریع و آسان، django-debug-toolbar بسیار مفید است. همچنین میتوانیم از ابزارهای پروفایل پایتون مانند ماژول hotshot برای تجزیه و تحلیل دقیق استفاده کنیم. در جنگو، می توانید از یکی از چندین قطعه میان افزار پروفایل برای نمایش خروجی هات شات در مرورگر استفاده کنید.
راهحلی که اخیراً برای ایجاد نمایه زنده وجود دارد، django-silk است. تمام درخواستها و پاسخها را در پایگاه داده پیکربندی شده ذخیره میکند و اجازه تجزیه و تحلیل انبوه در یک سشن کاربر را میدهد، که بدترین عملکردها را پیدا کند. همچنین میتواند با افزودن یک دکوراتور، هر قطعه کد پایتون را نمایه کند.
مانند قبل، نگاهی به برخی از راههای بهبود عملکرد Backend خواهیم انداخت. با این حال، با توجه به اینکه آنها به خودی خود موضوعات گسترده ای هستند، در بخش هایی دسته بندی شده اند. بسیاری از این موارد قبلاً در فصلهای قبلی پوشش داده شدهاند، اما برای ارجاع آسان در اینجا خلاصه شدهاند.
### تمپلیت ها
همانطور که مستندات نشان می دهد، شما باید تمپلیت لودر ذخیره شده را در مرحله تولید فعال کنید. این کار باعث میشود که هر بار که قالبها نیاز به رندر شدن داشته باشند، از کامپایل مجدد آن جلوگیری میشود. قالب ذخیره شده در حافظه پنهان اولین باری که نیاز است کامپایل می شود و سپس در حافظه ذخیره می شود. درخواست های بعدی برای همان الگو از حافظه ارائه می شود.
اگر متوجه شدید که زبان قالب دیگری مانند Jinja2 صفحه شما را به طور قابل توجهی سریعتر ارائه می کند، جایگزین کردن زبان قالب داخلی جنگو بسیار آسان است.
### دیتابیس
گاهی اوقات، Django ORM می تواند کد SQL ناکارآمد تولید کند. چندین الگوی بهینه سازی برای بهبود این امر وجود دارد که به شرح زیر است:
- کاهش بازدیدهای پایگاه داده با select_related: اگر از یک رابطه یک به یک یا یک کلید خارجی، در جهت فوروارد، برای تعداد زیادی از اشیاء استفاده می کنید، select_related() می تواند یک جوین را انجام دهد و تعداد بازدیدهای پایگاه داده را کاهش دهد.
- کاهش بازدید پایگاه داده با prefetch_related: برای دسترسی به متد ManyToManyField یا یک رابطه کلید خارجی در جهت معکوس، یا یک رابطه کلید خارجی در تعداد زیادی از اشیاء، استفاده از prefetch_related را برای کاهش تعداد بازدیدهای پایگاه داده در نظر بگیرید.
- واکشی فیلدهای مورد نیاز با ولیوها یا values_list: میتوانید با محدود کردن کوئریها برای بازگشت فیلدهای مورد نیاز و چشم پوشی کردن از نمونهسازی مدل با استفاده از values() یا values_list در زمان و استفاده از حافظه صرفهجویی کنید.
- مدلهای دینرمال شده: denormalization انتخابی، کارایی را از طریق کاهش جوین ها برای افزایش سازگاری دادهها بهبود میبخشد. همچنین می توان از آن برای پیش محاسبه مقادیر، مانند مجموع فیلدها یا گزارش وضعیت فعال در یک ستون اضافی استفاده کرد. در مقایسه با استفاده از مقادیر مشروح در پرس و جوها، فیلدهای غیرعادی شده اغلب ساده تر و سریعتر هستند.
- یک شاخص اضافه کنید: اگر یک کلید غیر اصلی در جستارهای شما زیاد جستجو می شود، db_index آن فیلد را در تعریف مدل خود روی True قرار دهید.
- ایجاد، به روز رسانی و حذف چندین ردیف به طور همزمان: چندین شی را می توان در یک کوئری پایگاه داده واحد با متدهای bulk_create()، update() و delete() اجرا کرد. با این حال، آنها با چندین اخطار مهم مانند چشم پوشی از متد save() در آن مدل همراه هستند. بنابراین، قبل از استفاده از آنها، اسناد را به دقت بخوانید.
بهعنوان آخرین راهحل، همیشه میتوانید عبارات SQL خام را با استفاده از تخصص کارایی پایگاه داده تنظیم کنید. با این حال، حفظ کد SQL می تواند در طول زمان دردناک باشد.
### ذخیره سازی
هر محاسباتی که زمان می برد می تواند از مزیت ذخیره سازی استفاده کند و نتایج از پیش محاسبه شده را سریعتر بازگرداند. با این حال، مشکل دادههای قدیمی است یا اغلب به عنوان یکی از سختترین چیزها در علوم کامپیوتر، عدم اعتبار کش ذکر میشود. این معمولاً زمانی دیده میشود که، با وجود بهروزرسانی صفحه، تعداد بازدیدهای ویدیوی YouTube تغییر نمیکند.
جنگو دارای یک سیستم کش انعطاف پذیر است که به شما امکان می دهد هر چیزی از یک قطعه قالب گرفته تا کل سایت را در حافظه پنهان ذخیره کنید. این انواع پشتیبان های قابل اتصال مانند ذخیره سازی مبتنی بر فایل یا مبتنی بر داده را شامل میشود.
اکثر سیستم های تولیدی از یک سیستم کش مبتنی بر حافظه مانند Redis یا Memcached استفاده می کنند. این صرفاً به این دلیل است که حافظه فرار بسیار سریعتر از ذخیره سازی مبتنی بر دیسک است.
چنین حافظه های کش برای ذخیره سازی داده های پرکاربرد اما زودگذر، مانند جلسات کاربر، ایده آل هستند..
### بکند سشن ذخیره شده
به طور پیش فرض، جنگو یوزر سشن خود را در پایگاه داده ذخیره می کند. این معمولاً برای هر درخواست بازیابی می شود. برای بهبود عملکرد، داده های سشن را می توان با تغییر تنظیمات SESSION_ENGINE در حافظه ذخیره کرد. به عنوان مثال، موارد زیر را در settings.py اضافه کنید تا دادههای جلسه را در حافظه پنهان خود ذخیره کنید:
- SESSION_ENGINE = "django.contrib.sessions.backends.cache"
از آنجایی که برخی از حافظه پنهان میتوانند دادههای قدیمی را که منجر به از دست رفتن دادههای جلسه میشود، از بین ببرد، ترجیح داده میشود از Redis یا Memcached به عنوان ذخیرهگاه سشن با محدودیتهای حافظه کافی برای پشتیبانی از حداکثر تعداد یوزر سشن های فعال استفاده شود.
### فریم ورک های ذخیره سازی
برای استراتژی های ذخیره سازی اولیه، ممکن است استفاده از فریم ورک ذخیره سازی آسان تر باشد. از جمله محبوب ترین ها می توان به django-cache-machine و django-cachalot اشاره کرد. آنها می توانند سناریوهای رایج را مدیریت کنند، مانند ذخیره خودکار نتایج جستجوها برای جلوگیری از بازدید از پایگاه داده هر بار که خواندن انجام می دهید.
ساده ترین آنها جنگو-کاچالوت، جانشین Johnny Cache است. به پیکربندی بسیار کمی نیاز دارد. این برای سایتهایی که دارای چندین خواندن و نوشتن نادر هستند (یعنی اکثریت قریب به اتفاق برنامهها) ایدهآل است، تمام پرسوجوهای خواندهشده جنگو ORM را به شیوهای ثابت ذخیره میکند.
### الگوهای ذخیره سازی
هنگامی که سایت شما شروع به دریافت ترافیک سنگین نمود، باید شروع به کاوش چندین استراتژی ذخیره سازی در سراسر پشته خود کنید. با استفاده از Varnish، یک سرور کش که بین کاربران شما و جنگو قرار می گیرد، بسیاری از درخواست های شما ممکن است حتی به سرور جنگو هم نرسند.
وارنیش می تواند باعث شود صفحات بسیار سریع بارگذاری شوند (گاهی اوقات صدها برابر سریعتر از حالت عادی). با این حال، در صورت استفاده نادرست، ممکن است صفحات ایستا را به کاربران شما ارائه دهد. Varnish را می توان به راحتی برای تشخیص صفحات پویا یا بخش های پویا از یک صفحه مانند سبد خرید پیکربندی کرد.
ذخیره سازی عروسک روسی (Russian doll caching) که در جامعه ریل محبوب است، یک الگوی جالب برای تمپلیت الگوی caching validation است. صفحه تایم لاین یک کاربر را با مجموعهای از پستها تصور کنید که هر کدام شامل فهرست تودرتویی از نظرات است. در واقع، کل صفحه را می توان به عنوان چندین لیست تو در تو از محتوا در نظر گرفت. در هر سطح، قطعه قالب رندر شده کش می شود.
بنابراین، اگر یک نظر جدید به یک پست اضافه شود، تنها پست مرتبط و کش های جدول زمانی باطل می شوند.
ابتدا محتوای کش را مستقیماً خارج از محتوای تغییر یافته باطل می کنیم و به تدریج حرکت می کنیم تا زمانی که به بیرونی ترین محتوا برسیم. وابستگی های بین مدل ها باید دنبال شود تا این الگو کار کند.
یکی دیگر از الگوهای رایج حافظه پنهان، کش کردن برای همیشه است. حتی پس از تغییر محتوا، کاربر ممکن است داده های قدیمی را از حافظه پنهان دریافت کند. با این حال، یک کار ناهمزمان، مانند کار Celery، نیز برای بهروزرسانی حافظه پنهان فعال میشود. همچنین می توانید به طور دوره ای کش را در یک بازه زمانی مشخص گرم کنید تا محتوا را تازه کنید.
اساساً، یک استراتژی ذخیره سازی موفق، بخش های استاتیک و پویا یک سایت را شناسایی می کند. برای بسیاری از سایتها، بخشهای پویا، دادههای خاص کاربر هستند زمانی که وارد سیستم میشوید.
ذخیره سازی نهان را به عنوان بخش جدایی ناپذیر عملکرد سایت خود تلقی نکنید. حتی اگر سیستم کش خراب شود، سایت باید به حالت کندتر اما کارآمد برگردد.
**Cranos**:
It was six in the morning and the SHIM building was surrounded by a
grey fog. Somewhere inside, a small conference room had been designated
the war room. For the last three hours, the SuperBook team had been
holed up here diligently executing their pre-go-live plan.
More than 30 users had logged on the IRC chatroom #superbookgolive
from various parts of the world. The chat log was projected on a giant
whiteboard. When the last item was struck off, Evan glanced at Steve.
Then, he pressed a key triggering the deployment process.
The room fell silent as the script output kept scrolling off the wall. One
error, Steve thought, just one error can potentially set them back by hours.
Several seconds later, the command prompt reappeared. It was live! The
team erupted in joy. Leaping from their chairs they gave high-fives to
each other. Some were crying tears of happiness. After weeks of
uncertainty and hard work, it all seemed surreal.
However, the celebrations were short-lived. A loud explosion from above
shook the entire building. Steve knew the second breach had begun. He
shouted to Evan, "don't turn on the beacon until you get my message",
and sprinted out of the room.
As Steve hurried up the stairway to the rooftop, he heard the sound of
footsteps above him. It was Madam O. She opened the door and flung
herself in. He could hear her screaming "no!" and a deafening blast shortly
after that.
By the time he reached the rooftop, he saw Madam O sitting with her back
against the wall. She was clutching her left arm and wincing in pain. Steve
slowly peered around the wall. At a distance, a tall bald man seemed to be
working on something with the help of two robots.
"He looks like...." Steve broke off, unsure of himself.
"Yes, it is Hart. Rather I should say he is Cranos now."
"What?"
"Yes, a split personality. A monster that laid hidden in Hart's mind for
years. I tried to help him control it. Many years back, I thought I had
stopped it from ever coming back. However, all this stress took a toll on
him. Poor thing, if only I could get near him."
Poor thing indeed, he nearly tried to kill her. Steve took out his mobile
and sent out a message to turn on the beacon. He had to improvise.
With his hands high in the air and fingers crossed, he stepped out. The
two robots immediately aimed directly at him. Cranos motioned them to
stop.
"Well, who do we have here? Mr. SuperBook himself. Did I crash into
your launch party, Steve?"
"It was our launch, Hart."
"Don't call me that", growled Cranos. "That guy was a fool. He wrote the
Sentinel code but he never understood its potential. I mean, just look at
what Sentinels can do, unravel every cryptographic algorithm known to
man. What happens when it enters an intergalactic network?"
The hint was not lost on Steve. "SuperBook?" he asked slowly.
Cranos let out a malicious grin. Behind him, the robots were busy wiring
into SHIM's core network. "While your SuperBook users will be busy
playing SuperVille, the tentacles of Sentinel will spread into new
unsuspecting worlds. Critical systems of every intelligent species will be
sabotaged. The Supers will have to bow to a new intergalactic supervillain
Cranos."
As Cranos was delivering this extended monologue, Steve noticed a
movement of the corner of his eye. It was Acorn, the super-intelligent
squirrel, scurrying along the right edge of the rooftop. He also spotted
Hexa hovering strategically on the other side. He nodded at them.
Hexa levitated a garbage bin and flung it towards the robots. Acorn
distracted them with high-pitched whistles. "Kill them all!" Cranos said
irritably. As he turned to watch his intruders, Steve fished out his phone,
dialed into FaceTime and held it towards Cranos.
"Say hello to your old friend, Cranos," said Steve.
Cranos turned to face the phone and the screen revealed Madam O's face.
With a smile, she muttered under her breath, "Taradiddle Bumfuzzle!"
The expression on Cranos's face changed instantly. The seething anger
disappeared. He now looked like a man they had once known.
"What happened?" asked Hart confused.
"We thought we had lost you," said Madam O over the phone. "I had to
use hypnotic trigger words to bring you back."
Hart took a moment to survey the scene around him. Then, he slowly
smiled and nodded at her.
----------------------------------------------------
One Year Later
Who would have guessed Acorn would turn into an intergalactic singing
sensation in less than a year? His latest album Acorn Unplugged debuted
at the top of Billboard's Top 20 chart. He threw a grand party in his new
white mansion overlooking a lake.
The guest list included superheroes, pop stars, actors, and celebrities of all
sorts.
"So, there was a singer in you after all," said Captain Obvious holding a
martini.
"I guess there was," replied Acorn. He looked dazzling in a golden tuxedo
with all sorts of bling-bling.
Steve appeared with Hexa in tow, who looked ravishing in a flowing
silver gown.
"Hey Steve, Hexa. It has been a while. Is SuperBook still keeping you late
at work, Steve?"
"Not so much these days. Knock on wood," replied Hexa with a smile.
"Ah, you guys did a fantastic job. I owe a lot to SuperBook. My first single,
'Warning: Contains Nuts', was a huge hit in the Tucana galaxy. They
watched the video on SuperBook more than a billion times!"
"I am sure every other superhero has a good thing to say about SuperBook
too. Take Blitz. His AskMeAnything interview won back the hearts of his
fans. They were thinking that he was on experimental drugs all this time.
It was only when he revealed that his father was Hurricane that his
powers made sense."
"By the way, how is Hart doing these days?"
"Much better," said Steve. "He got professional help. The sentinels were
handed back to S.H.I.M. They are developing a new quantum
cryptographic algorithm that will be much more secure."
"So, I guess we are safe until the next supervillain shows up," said Captain
Obvious hesitantly.
"Hey, at least the beacon works," said Steve, and the crowd burst into
laughter.
### خلاصه
در این فصل آخر، ما به رویکردهای مختلف برای پایدار، قابل اعتماد و سریع کردن برنامه جنگو شما نگاه کردیم. به عبارت دیگر، آن را آماده تولید کنیم. اگرچه مدیریت سیستم ممکن است به خودی خود یک رشته کامل باشد، دانش منصفانه از وب استک ضروری است. چندین گزینه میزبانی از جمله PaaS، VPS و Serverless را بررسی کردیم.
همچنین چندین ابزار استقرار خودکار و یک سناریوی استقرار معمولی را بررسی کردیم. در نهایت، چندین تکنیک را برای بهبود عملکرد frontend و backend پوشش دادیم.
مهمترین نقطه عطف یک وب سایت تکمیل و رساندن آن به مرحله تولید است. با این حال، این به هیچ وجه پایان سفر توسعه شما نیست. ویژگیها، تغییرات و بازنویسیهای جدیدی وجود خواهد داشت.
هر بار که کد را دوباره مرور میکنید، از این فرصت استفاده کنید تا یک قدم به عقب برگردید و طرحی تمیزتر پیدا کنید، یک الگوی پنهان را شناسایی کنید یا به پیادهسازی بهتری فکر کنید. توسعه دهندگان دیگر، و شاید خود آینده شما، از شما برای آن تشکر خواهند کرد.
================================================
FILE: Appendix-A-Python2-Versus-Python3/README.md
================================================
# پایتون 2 در مقابل پایتون 3
تمام نمونه کدهای این کتاب برای پایتون 3.6 نوشته شده است.
به جز تغییرات بسیار جزیی، آنها باید در پایتون 2.7 نیز کار کنند.
نویسنده بر این باور است که پایتون 3 از نقطه ی اوج برای انتخاب ترجیحی برای پروژه های جدید جنگو عبور کرده است.
قرار بود توسعه ی پایتون 2.7 در سال 2015 به پایان برسد اما برای 5 سال دیگر تا سال 2020 تمدید شد.
پایتون 2.8 وجود نخواهد داشت. همان طور که در **فصل 2**، طراحی برنامه ذکر شد،
بیشتر توزیع های اصلی لینوکس و فروشندگان ابری به طور کامل به استفاده از Python 3 به عنوان پیش فرض یا پشتیبانی از آن روی آورده اند.
این پیوست برای توسعه دهندگانی نوشته شده که با پایتون 3 آشنایی ندارند.
پیشینه ی تاریخی مختصر و تغییرات ترکیبی در پایتون 3 مورد بحث قرار گرفته است.
به جای ارائه ی پوشش جامع از ویژگی های Python 3، تنها موارد مربوط به توسعه دهندگان جنگو پوشش داده شده است.
### پایتون 3
پایتون 3 از سر ناچاری متولد شد.
یکی از مزاحمت های اصلی پایتون 2، مدیریت ناسازگار آن با کاراکترهای غیرانگلیسی
بود (که به طور معمول به عنوان خطای بدنام UnicodeDecode نشان داده می شود).
Guido پروژه Python 3 را برای پاکسازی تعدادی از چنین مشکلات زبانی و در عین حال شکستن سازگاری با نسخه های پیشین، آغاز کرد.
اولین نسخه ی آلفا پایتون 3.0 در آگوست 2007 ساخته شد.
از آن زمان، پایتون 2 و پایتون 3 چندین سال به طور موازی توسط تیم توسعه ی اصلی توسعه داده شده اند.
در نهایت، انتظار می رود پایتون 3 آینده ی این زبان باشد.
### پایتون 3 برای جنگویی ها
این بخش مهم ترین تغییرات پایتون 3 را از دیدگاه توسعه دهندگان جنگو پوشش می دهد.
برای درک لیست کامل تغییرات، به بخش خواندن توصیه شده در پایان مراجعه کنید.
مثالها در پایتون 2 و پایتون 3 ارائه شدهاند.
بسته به نوع نصب شما، ممکن است لازم باشد همه دستورات پایتون 3 از پایتون به پایتون 3 تغییر کنند.
**همه متدهای «__unicode__» را به «__str__» تغییر دهید**
در پایتون 3، متد «()__str__» برای نمایش رشتهای مدلهای شما
به جای متد «()__unicode__» با صدای نامناسب فراخوانی میشود.
این یکی از واضح ترین راه های شناسایی کدهای پورت شده پایتون 3 است:
**python 2**
```python
class Person(models.Model):
name = models.TextField()
def __unicode__(self):
return self.name
```
**python 3**
```python
class Person(models.Model):
name = models.TextField()
def __str__(self):
return self.name
```
این نشان دهنده ی تفاوت در نحوه ی برخورد پایتون 3 با رشته ها است.
در Python 2، نمایش قابل خواندن توسط انسان یک کلاس را
می توان با «()__str__» (بایت) یا «()__unicode__» (متن) برگرداند.
با این حال، در پایتون 3، نمایش قابل خواندن به سادگی توسط «()__str__» (متن) برگردانده می شود.
### همه کلاس ها از شی ارث می برند
پایتون 2 دارای دو نوع کلاس است: سبک قدیمی (کلاسیک) و سبک جدید.
کلاس های سبک جدید کلاس هایی هستند که به طور مستقیم یا غیرمستقیم از شی به ارث می برند.
فقط کلاسهای سبک جدید میتوانند از ویژگیهای پیشرفته پایتون مانند اسلاتها، توصیفگرها و ویژگیها استفاده کنند.
بسیاری از این ها توسط جنگو استفاده می شود.
با این حال، کلاس ها به دلایل سازگاری هنوز به طور پیش فرض قدیمی هستند.
در پایتون 3، کلاسهای قدیمی دیگر وجود ندارند.
همانطور که در جدول زیر مشاهده می شود،
حتی اگر به صراحت هیچ کلاس والد را ذکر نکنید،
کلاس شی به عنوان پایه وجود خواهد داشت.
بنابراین، همه کلاس ها به سبک جدید هستند:
**python 2**
```python
>>> class CoolMixin:
... pass
>>> CoolMixin.__bases__
()
```
**python 3**
```python
>>> class CoolMixin:
... pass
>>> CoolMixin.bases
(