Django Rest Framework (DRF)
در درس های رایگان DRF حداقل نیازهایی که برای کار در شرکت ها و یا انجام پروژه ها نیاز دارید، ارائه شده است.
13
درس
- معرفی Django Rest Framework پس از ساخت مدلها در جنگو، اغلب نیاز میشود که دادهها در اختیار برنامههای موبایل یا فرانتاندهایی مانند React قرار بگیرد. جنگو به صورت پیشفرض سازوکاری اختصاصی برای این نوع ارتباطات فراهم نمیکند. در چنین شرایطی، نیاز به یک واسط داریم. واسطی که مدلها را به خروجی JSON تبدیل کند. درخواستهای GET و POST را مدیریت نماید. و امکان ارتباط اپلیکیشنهای دیگر با سایت را فراهم سازد. به این واسط، API گفته میشود. Django REST Framework (یا به اختصار DRF) مجموعهای از ابزارهای آماده برای ساخت همین نوع واسطهاست. بدون اینکه توسعهدهنده مجبور باشد از صفر منطق کوئریپارامترها یا مدیریت وضعیتهای خطا را پیادهسازی کند. در این درس، با مفاهیم پایهای API آشنا میشوید. دلایل استفاده از DRF به جای نوشتن دستی API بررسی میگردد. همچنین توضیح داده میشود که چرا جنگوی خالص به تنهایی گزینه مناسبی برای پیادهسازی API نیست. محتوای این درس جنبه تئوری دارد. اما تلاش شده هر مفهوم همراه با مثال عینی ارائه شود. هدف این است که پس از مطالعه این درس، بدانید دقیقاً DRF در چه مرحلهای از توسعه یک پروژه به کار میآید.
- نصب DRF در درس قبل فهمیدید DRF چیست و چه مشکلاتی از جنگوی خالص را حل میکند. حالا نوبت رسیده که دست به کد شوید. نصب drf اولین قدم عملی برای ساختن API با جنگو است. بدون این مرحله، هیچکدام از ابزارهایی که معرفی شد (سریالایزر، ویوست، احراز هویت آماده) در دسترس شما نخواهند بود. نصب خودش کار سادهای است. یک خط دستور در ترمینال. اما چند نکته ظریف دارد. مثلاً باید DRF را به INSTALLED_APPS اضافه کنید. در غیر اینصورت حتی اگر نصب شده باشد، جنگو آن را نمیبیند. همچنین بعضی کتابخانههای جانبی مثل django-filter و markdown اگر نباشند، بعضی قابلیتهای DRF کار نمیکنند. در این درس تک تک این موارد را میبینید. در انتهای درس، یک ویو تستی مینویسیم. با باز کردن آن در مرورگر، مطمئن میشوید نصب drf به درستی انجام شده و محیط شما آماده درسهای بعدی است.
- نوشتن اولین API با Function-Based View تا اینجا DRF را نصب کردهاید. تنظیمات اولیه را انجام دادهاید. حتی یک ویو تستی با APIView نوشتید و دیدید که Browsable API چطور کار میکند. اما آن ویو فقط یک پیام ساده برمیگرداند. بدون مدل، بدون دیتابیس، بدون هیچ منطق واقعی. وقتش رسیده که دستتان به کد واقعی API عادت کند. در این درس، با سادهترین روش ممکن یک API مینویسیم: Function-Based View. نیازی به کلاس پیچیده نیست. نیازی به سریالایزر هم نداریم. فقط یک تابع پایتونی با یک دکوریتور خاص. بعد از نوشتن API، یاد میگیرید چطور با Postman آن را تست کنید. Postman ابزاری است که هر توسعهدهنده بکاند باید بلد باشد. بدون آن، Testing APIها خستهکننده و وقتگیر میشود. در انتهای این درس، شما میتوانید: یک API با متد GET بنویسید پارامتر از مسیر (Dynamic URL) بگیرید Query Parameter دریافت کنید همه را با Postman تست کنید این درس پلی است بین مباحث تئوری و کار عملی واقعی. بعد از این درس، وارد بحث سریالایزرها میشویم. اما فعلاً تمرکز روی سادگی و درک جریان درخواست و پاسخ است. اگر محیط جنگو و DRF شما آماده است، بیایید شروع کنیم.
- سریالایز ها در DRF تا اینجا یاد گرفتید چطور یک ویو ساده با @api_view بنویسید. در آن ویوها، داده را دستی به دیکشنری تبدیل میکردیم. برای هر بار تبدیل، کد جداگانه مینوشتیم. این روش برای پروژههای کوچک شاید کار کند. اما وقتی مدل شما ۲۰ فیلد داشته باشد، نوشتن این کد تبدیل برای هر مدل تکراری و خستهکننده میشود. اینجا جایی است که سریالایزرها وارد میشوند. سریالایزر در DRF کاری شبیه همان فرمها در جنگوی معمولی انجام میدهد. داده مدل را میگیرد و به JSON تبدیل میکند. JSON دریافتی از کاربر را میگیرد، اعتبارسنجی میکند، و به مدل تبدیل مینماید. به همین دلیل به آن قلب DRF میگویند. بدون سریالایزر، هیچکدام از ویوهای پیشرفتهتر (کلاسبیس، جنریک، ویوست) کار نمیکنند. در این درس از صفر شروع میکنیم. اول با یک Serializer ساده کار میکنیم. بعد میبینیم ModelSerializer چطور کد ما را کوتاهتر میکند. در انتها یاد میگیرید چطور اعتبارسنجی سفارشی بنویسید و خروجی سریالایزر را تغییر دهید. اگر درسهای قبل را خوب متوجه شدهاید، برای این درس کاملاً آماده هستید. تنها چیزی که نیاز دارید یک مدل ساده است که همان اول درس میسازیم.
- کلاس بیس ویو ها در DRF تا الان دو روش برای نوشتن ویو در DRF امتحان کردهاید. اولی با @api_view دکوریتور روی توابع ساده. همان روشی که در درس های قبلی کار کردید. این روش برای چند خط کد و پروژههای کوچک، مناسب است. دومی با Serializerها که در درس قبل یاد گرفتید. حالا مدل دارید، Serializer دارید، اما ویوها هنوز تابعی هستند. اینجا یک مشکل ظاهر میشود. فرض کنید میخواهید پنج API مختلف بنویسید. هر کدام نیاز به منطق مشابهی دارند. مثلاً همه باید چک کنند کاربر لاگین کرده یا نه. یا همه باید خطاهای مشابهی برگردانند. با روش تابعی، مجبورید این کدهای تکراری را در هر تابع بنویسید. یا توابع کمکی بسازید و در جای دیگر صدا بزنید. کلاسبیس ویوها این مشکل را حل میکنند. APIView پایهترین کلاس در DRF است. با آن میتوانید متدهای GET، POST، PUT، DELETE را جداگانه در یک کلاس تعریف کنید. کد تمیزتر میشود. قابلیت استفاده مجدد بالا میرود. در این درس، یک CRUD کامل با APIView مینویسیم. یعنی چهار عمل اصلی: خواندن لیست، خواندن جزئیات، ساختن، بروزرسانی، و حذف. همچنین یاد میگیرید چطور داده را از request.data و request.query_params بخوانید. و چطور پاسخ را با Response برگردانید. اگر درس Serializerها را خوب متوجه شدهاید، این درس برای شما ساده خواهد بود. چون منطق اصلی همان است. فقط ساختار ویوها را از تابع به کلاس تغییر میدهیم.
- ویو های جنریک در DRF در درس قبل، با APIView یک CRUD کامل نوشتید. پنج متد مختلف. دو کلاس جداگانه. منطق پیدا کردن شیء را در سه جای مختلف تکرار کردید. کار میکرد. اما کد زیادی داشت. حالا فرض کنید بخواهید همین کار را برای مدل Product یا User هم بنویسید. دوباره همان کدهای تکراری را مینویسید. دوباره get_object میسازید. دوباره اعتبارسنجی دستی میکنید. اینجا جایی است که ویوهای جنریک وارد میشوند. ListCreateAPIView و RetrieveUpdateDestroyAPIView دو کلاس آماده در DRF هستند. خیلی از کارهایی که شما در APIView دستی نوشتید، اینها از قبل برایتان انجام میدهند. نیازی به نوشتن get_object نیست. نیازی به چک کردن ۴۰۴ نیست. نیازی به تکرار منطق در چند متد ندارید. در این درس، با همین دو کلاس، کل CRUD قبلی را در کمتر از ۱۰ خط کد بازنویسی میکنید. همچنین یاد میگیرید چطور با get_queryset و get_serializer_class رفتار پیشفرض را تغییر دهید. و در انتها با mixins آشنا میشوید؛ قطعات کوچکی که میتوانید آنها را ترکیب کنید و ویوهای سفارشی بسازید. اگر درس APIView را خوب درک کرده باشید، این درس برای شما مثل یک اتوماتیکسازی شیرین خواهد بود.
- ویو ست ها و روتر ها تا الان سه روش برای نوشتن ویو در DRF یاد گرفتهاید. روش اول: Function-Based View با دکوریتور @api_view. ساده اما برای پروژههای بزرگ کافی نیست. روش دوم: APIView. کنترل کامل روی منطق ویو. اما برای هر مدل باید چندین کلاس جداگانه بنویسید. روش سوم: Generic Views مثل ListCreateAPIView. کدها خیلی کوتاه شدند. اما همچنان برای هر مدل به دو کلاس مجزا نیاز دارید. یکی برای لیست و ساختن، دیگری برای جزئیات و بروزرسانی و حذف. حالا فرض کنید پروژه شما ده مدل داشته باشد. باید بیست کلاس بنویسید. هر کدام با مسیرهای جداگانه. اینجا ViewSet وارد میشود. یک ViewSet همه عملیاتهای CRUD را در یک کلاس جمع میکند. دیگر خبری از دو کلاس جداگانه نیست. فقط یک کلاس برای هر مدل. اما این همه ماجرا نیست. ViewSetها با Router همراه میشوند. دیگر نیازی نیست urlpatterns را دستی پر کنید. Router خودکار مسیرهای مربوط به هر عملیات را میسازد. در این درس، از ModelViewSet شروع میکنیم. سپس ReadOnlyModelViewSet را یاد میگیرید. بعد با DefaultRouter آشنا میشوید. در انتها هم یاد میگیرید چطور متدهای سفارشی مثل activate/ را با @action به ViewSet اضافه کنید. اگر Generic Views را خوب فهمیده باشید، ViewSet برای شما یک ارتقاء طبیعی و شیرین خواهد بود.
- احراز هویت و مجوز ها در DRF تا الان چندین API ساختید. مقالات را میتوانید ببینید، بسازید، ویرایش کنید و حذف نمایید. اما یک مشکل بزرگ وجود دارد. همه این کارها را هر کسی میتواند انجام دهد. حتی کاربری که لاگین نکرده. حتی کسی که هیچ ارتباطی با سایت شما ندارد. در دنیای واقعی، اینطور نیست. یک مقاله را فقط نویسنده آن باید بتواند ویرایش کند. یک محصول را فقط ادمین باید بتواند حذف کند. یک پست خصوصی را فقط خود کاربر باید ببیند. اینجا دو مفهوم وارد میشود: احراز هویت و مجوزها. احراز هویت یعنی تشخیص هویت کاربر. ببینیم چه کسی وارد شده. توکن دارد یا نه. لاگین کرده یا نه. مجوزها یعنی بعد از اینکه فهمیدیم کاربر کیست، مشخص کنیم چه کاری مجاز است انجام دهد. آیا اجازه حذف این مقاله را دارد؟ آیا میتواند این محصول را ببیند؟ در این درس، با انواع روشهای احراز هویت در DRF آشنا میشوید. از BasicAuthentication ساده تا TokenAuthentication که استاندارد اصلی در APIهاست. همچنین یاد میگیرید چطور دسترسیها را با IsAuthenticated، IsAdminUser و AllowAny مدیریت کنید. در انتها، DjangoObjectPermissions را میبینید که اجازه میدهد دسترسی را روی هر شیء به صورت جداگانه کنترل کنید. و یاد میگیرید چطور مجوزهای سفارشی برای نیازهای خاص خودتان بسازید. این درس برای ورود به بازار کار بسیار مهم است. چون در هیچ پروژه جدیای، همه کاربران به همه چیز دسترسی ندارند. برای این درس، به مدل Article خود یک فیلد author اضافه میکنیم تا مالک هر مقاله را مشخص کنیم.
- فیلتر، جستجو و مرتبسازی در DRF تا الان APIهای ساختید که همه دادهها را یکجا برمیگردانند. مثلاً GET /api/articles/ لیست همه مقالات را نشان میدهد. بدون هیچ انتخابی. بدون هیچ ترتیبی. حالا فرض کنید دیتابیس شما هزار تا مقاله دارد. کاربر نمیخواهد همه را یکجا ببیند. فقط میخواهد مقالات خودش را ببیند. یا آخرین مقالات را اول ببیند. یا بین عناوین جستجو کند. اینجا فیلتر، جستجو و مرتبسازی drf وارد میشوند. فیلتر یعنی به کاربر اجازه دهید فقط زیرمجموعهای از دادهها را ببیند. مثلاً فقط مقالات یک نویسنده خاص. جستجو یعنی کاربر یک کلمه وارد کند، سیستم آن کلمه را در عنوان یا محتوا پیدا کند و نتایج مرتبط را برگرداند. مرتبسازی یعنی کاربر مشخص کند بر اساس چه فیلدی و به چه ترتیبی نتایج نشان داده شود. جدیدترین اول، یا قدیمیترین اول. در این درس، سه روش برای پیادهسازی این قابلیتها یاد میگیرید. اول با request.query_params ساده شروع میکنیم. بعد سراغ django-filter میرویم که حرفهایتر است. در انتها با SearchFilter و OrderingFilter آشنا میشوید که جستجو و مرتبسازی را به صورت خودکار انجام میدهند. این قابلیتها برای هر API که دادههای زیادی دارد، ضروری هستند. کاربران عادی انتظار دارند بتوانند دادهها را فیلتر و مرتب کنند. برای این درس، همان مدل Article قبل را داریم. فقط چند مقاله نمونه به آن اضافه میکنیم تا تست کردن راحتتر باشد.
- صفحه بندی در DRF تا الان APIهایی ساختید که همه دادهها را یکجا برمیگردانند. این روش برای وقتی که ده تا مقاله دارید، خوب است. اما وقتی تعداد رکوردها به صد یا هزار یا ده هزار میرسد، چه اتفاقی میافتد؟ سرور مجبور است همه را از دیتابیس بخواند. بعد همه را به JSON تبدیل کند. بعد همه را از طریق شبکه بفرستد. کاربر هم مجبور است منتظر بماند تا همه این دادهها دانلود شوند. نتیجه؟ کندی سرور، مصرف زیاد پهنای باند، و用户体验 بد. راه حل ساده است: همه دادهها را یکجا نفرست. تکه تکه بفرست. به این میگویند صفحهبندی. کاربر صفحه اول را میخواهد. شما ده رکورد اول را میفرستید. همراه با یک لینک به صفحه بعد. کاربر که صفحه دوم را خواست، ده رکورد بعدی را میفرستید. در این درس، سه روش صفحهبندی در DRF را یاد میگیرید. PageNumberPagination رایجترین روش. همان چیزی که در اکثر سایتها میبینید. با پارامتر ?page=2. LimitOffsetPagination روشی شبیه به APIهای بزرگ مثل گوگل. با پارامتر ?limit=10&offset=20. CursorPagination برای دادههای خیلی بزرگ و نرمافزارهای زمانواقعی. سریعتر و قابل اعتمادتر از دو روش قبلی. همچنین یاد میگیرید چطور تنظیمات صفحهبندی را یک بار برای کل پروژه تعیین کنید. و چطور در یک ویو خاص، تنظیمات متفاوتی اعمال کنید. این درس برای وقتی است که دیتابیس شما بزرگ میشود و کاربرانتان خواهان سرعت هستند.
- نسخه بندی API در DRF تا الان چندین API ساختید. فیلتر و جستجو و صفحهبندی دارید. احراز هویت و مجوزها را هم اضافه کردید. اما یک سؤال مهم هنوز بیجواب مانده است. اگر بخواهید یک فیلد را تغییر دهید، چه اتفاقی میافتد؟ مثلاً فعلاً مدل Product شما فیلد name دارد. یک ماه بعد تصمیم میگیرید اسم آن را بگذارید title. برای پروژه جدیدتان عالی است. اما اپلیکیشن موبایل کاربران قدیمی هنوز name را میفرستد. وبسایتهای دیگری که از API شما استفاده میکنند، همان name را انتظار دارند. اگر مستقیم تغییر دهید، همه چیز برایشان خراب میشود. این مشکل را نسخهبندی API حل میکند. نسخهبندی یعنی چند نسخه از API را همزمان نگه دارید. کاربران قدیمی به نسخه قدیمی متصل بمانند. کاربران جدید از نسخه جدید استفاده کنند. هر کسی بدون مشکل به کار خود ادامه دهد. در این درس، دو روش اصلی نسخهبندی را یاد میگیرید. روش اول: URLPathVersioning. نسخه را در خود آدرس قرار میدهید. مثل /api/v1/products/ و /api/v2/products/. ساده و شفاف. روش دوم: AcceptHeaderVersioning. نسخه را در هدر درخواست مشخص میکنید. برای APIهایی که نمیخواهند آدرسشان شلوغ شود، مناسب است. همچنین یاد میگیرید چطور نسخهبندی را در DRF فعال کنید و در ویوها به نسخه درخواست دسترسی داشته باشید. این درس برای وقتی است که API شما رشد میکند و چندین مشتری به آن متصل هستند. نسخهبندی به شما اجازه میدهد بدون ترس از خراب کردن کار دیگران، API خود را بهبود ببخشید.
- مستند سازی خودکار API در DRF تا الان چندین API حرفهای با DRF ساختهاید. فیلتر و جستجو و صفحهبندی دارید. احراز هویت و مجوزها را اضافه کردید. نسخهبندی را هم یاد گرفتید. اما یک چیز هنوز کم است: مستندات. اگر مستندات خوبی نداشته باشید، هیچکس نمیداند چطور از API شما استفاده کند. توسعه دهنده ها مجبور میشوند کد شما را بخوانند. وقتشان تلف میشود. احتمال دارد از API شما دوری کنند. نگهداری مستندات دستی هم تقریباً غیرممکن است. چون هر بار که API را تغییر میدهید، باید مستندات را هم بهروز کنید. یک جا را فراموش میکنید. مستندات از کد جلوتر میماند یا عقب. دیگر نمیشود به آن اعتماد کرد. راه حل: مستندسازی خودکار. یک بار ابزار را تنظیم میکنید. بعد هر تغییری در کد بدهید، مستندات خودکار بهروز میشود. همیشه دقیق. همیشه قابل اعتماد. در این درس، دو کتابخانه محبوب را یاد میگیرید. drf-spectacular که نسخه OpenAPI 3.1 تولید میکند و توسط خود DRF توصیه میشود. و drf-yasg که OpenAPI 2 تولید میکند و سالهاست در پروژههای زیادی استفاده شده است. با Swagger UI آشنا میشوید. یک صفحه تعاملی که توسعهدهندهها میتوانند مستقیماً در مرورگر API شما را تست کنند. بدون Postman، بدون نوشتن کد. ReDoc را هم میبینید. یک خروجی مرتب و خوانا برای مطالعه و چاپ. در انتها یاد میگیرید چطور با docstring و توضیحات داخل ویوها، مستندات را کاملتر کنید. این درس API شما را از یک محصول خوب به یک محصول حرفهای تبدیل میکند. مستندات خوب یعنی مشتریان راضیتر و زمان پشتیبانی کمتر.
- نکات ضروری برای کار در شرکت یا پروژه واقعی تا الان ابزارهای DRF را یکی یکی یاد گرفتید. سریالایزر، ویوهای مختلف، احراز هویت، فیلتر، صفحهبندی، نسخهبندی و مستندسازی. اما شرکتها فقط ابزار بلد بودن را نمیخرند. آنها راه حل میخرند. آنها کد تمیز و قابل نگهداری میخرند. آنها امنیت و کارایی میخرند. این درس پلی است بین «بلدم» و «میتوانم در محیط واقعی کار کنم». اینجا چند موضوع خیلی کاربردی را جمع کردهام. موضوعاتی که در مصاحبههای شغلی از شما میپرسند. در کدهای تولیدی شرکتها مدام میبینید. و در هیچکدام از درسهای قبلی به تفصیل به آنها پرداخته نشده است. اول: مقایسه نهایی APIView، Generic Views و ViewSet. کدام را کی استفاده کنیم؟ راهنمایی برای انتخاب درست در پروژههای واقعی. دوم: مدیریت خطاها و ارورهای استاندارد. هیچ API بدون خطا کار نمیکند. اما مهم این است که خطاها را چطور به کلاینت برگردانید. طوری که قابل فهم باشد و امنیت را هم حفظ کند. سوم: سریالایزر تو در تو (Nested Serializer). فرض کنید یک مقاله چند کامنت دارد. یا یک سفارش چند محصول. چطور همه را یکجا برگردانید؟ بدون نوشتن کد اضافی. چهارم: محدودیت درخواست (Throttling). اگر کاربری هزار بار در یک دقیقه به API شما حمله کند، چه کار میکنید؟ بدون این قابلیت، سرورتان خیلی زود از کار میافتد. پنجم: ذخیره فایل با DRF. آپلود عکس پروفایل، فایل ضمیمه مقاله، یا هر فایل دیگری. با چالشهای خاص خودش مثل امنیت و حجم. این درس آخر، شما را برای ورود به بازار کار آماده می کند.