در درس قبل فهمیدید DRF چیست و چه مشکلاتی از جنگوی خالص را حل میکند. حالا نوبت رسیده که دست به کد شوید.
نصب drf اولین قدم عملی برای ساختن API با جنگو است. بدون این مرحله، هیچکدام از ابزارهایی که معرفی شد (سریالایزر، ویوست، احراز هویت آماده) در دسترس شما نخواهند بود. نصب خودش کار سادهای است. یک خط دستور در ترمینال. اما چند نکته ظریف دارد. مثلاً باید DRF را به INSTALLED_APPS اضافه کنید. در غیر اینصورت حتی اگر نصب شده باشد، جنگو آن را نمیبیند.
همچنین بعضی کتابخانههای جانبی مثل django-filter و markdown اگر نباشند، بعضی قابلیتهای DRF کار نمیکنند. در این درس تک تک این موارد را میبینید.
در انتهای درس، یک ویو تستی مینویسیم. با باز کردن آن در مرورگر، مطمئن میشوید نصب drf به درستی انجام شده و محیط شما آماده درسهای بعدی است.
ایجاد محیط مجاز (Virtual Environment) و نصب Django
قبل از نصب DRF، به یک پروژه جنگو فعال نیاز دارید. اگر قبلاً جنگو را نصب و تنظیم کردهاید، میتوانید از همین پروژه استفاده کنید.
در غیر این صورت، ابتدا درس مربوط به نصب جنگو و ساخت محیط مجازی را در آکادمی مطالعه کنید. تمام مراحل از ساخت محیط با venv تا نصب جنگو و بررسی نسخه در آن درس توضیح داده شده است.
پس از آماده شدن پروژه جنگو، به این درس برگردید و مرحله بعدی یعنی نصب DRF را ادامه دهید.
از این لحظه به بعد، تمام دستورات مربوط به این پروژه باید در حالی اجرا شوند که محیط مجاز فعال است. هر بار ترمینال را میبندید و دوباره باز میکنید، باید دوباره محیط را فعال کنید.
نصب Django REST Framework با pip
بعد از فعال بودن محیط مجاز و نصب جنگو، نصب DRF فقط یک خط کد است:
pip install djangorestframework
این دستور آخرین نسخه پایدار DRF را به همراه وابستگیهای اصلی آن نصب میکند.
اگر میخواهید نسخه مشخصی نصب کنید، مثل جنگو میتوانید شماره نسخه را تعیین کنید:
pip install djangorestframework==3.15.2
پیشنهاد میکنم ابتدا بدون تعیین نسخه نصب کنید. مگر اینکه پروژه شما به نسخه خاصی محدود شده باشد.
نصب کتابخانههای جانبی ضروری
DRF برای بعضی از قابلیتهای خود به کتابخانههای کمکی نیاز دارد. این کتابخانهها اجباری نیستند. اما اگر نباشند، بعضی امکانات کار نمیکند.
markdown
این کتابخانه برای قابلیت Browsable API استفاده میشود. اگر آن را نصب نکنید، صفحات مرورگر API همچنان کار میکنند اما فرمتدهی خوبی نخواهند داشت.
pip install markdown
django-filter
برای افزودن قابلیت فیلتر پیشرفته به APIها به کار میرود. بدون آن، نمیتوانید به راحتی شرطهای پیچیده مثل قیمت کمتر از ۱۰۰ هزار تومان را پیادهسازی کنید.
pip install django-filter
یک کتابخانه دیگر به اسم djangorestframework-simplejwt برای احراز هویت با توکن JWT وجود دارد. اما فعلاً به آن نیاز ندارید. در درس احراز هویت نصبش میکنیم.
بررسی موفقیت نصب با pip list
بعد از نصب، میتوانید لیست تمام کتابخانههای نصب شده در محیط مجاز خود را ببینید:
pip list
خروجی چیزی شبیه این خواهد بود:
Package Version
--------------------- ---------
Django 4.2
djangorestframework 3.15.2
django-filter 24.3
markdown 3.6
pip 24.0
وجود djangorestframework در این لیست یعنی نصب موفق بوده است.
برای بررسی دقیقتر، میتوانید نسخه DRF را هم جداگانه ببینید:
pip show djangorestframework
این دستور اطلاعات بیشتری مثل محل نصب و وابستگیها را نشان میدهد.
یک نکته مهم
نصب این کتابخانهها فقط اولین قدم است. تا وقتی DRF را به INSTALLED_APPS اضافه نکنید، جنگو آن را نمیشناسد. این کار را در بخش بعدی انجام میدهیم.
افزودن DRF به INSTALLED_APPS در settings.py
نصب DRF با pip کافی نیست. جنگو باید بداند که این اپلیکیشن را فعال کنید. این کار در فایل settings.py و در لیست INSTALLED_APPS انجام میشود.
فایل settings.py پروژه خود را باز کنید. لیستی به نام INSTALLED_APPS پیدا خواهید کرد. معمولاً در ابتدای فایل قرار دارد.
'rest_framework' را به این لیست اضافه کنید:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
# Your apps
'myapp',
]
توجه کنید که 'rest_framework' را داخل کوتیشن تکی یا دابل نوشتهاید. هر دو مجاز است.
بعد از این تغییر، اگر سرور توسعه را روشن کرده باشید، باید آن را متوقف و دوباره راهاندازی کنید:
python manage.py runserver
بدون این کار، تغییرات اعمال نمیشود.
تفاوت ترتیب اپها در INSTALLED_APPS (آیا اهمیت دارد؟)
ترتیب اپها در INSTALLED_APPS در بعضی موارد مهم است. اما برای DRF جای خاصی ندارد.
جنگو وقتی یک اپلیکیشن را میخواند، ترتیب لیست را از بالا به پایین طی میکند. اپلیکیشنهایی که بالاتر قرار دارند، زودتر بارگذاری میشوند.
چه زمانی ترتیب مهم است؟
- وقتی دو اپلیکیشن قالب (template) با نام یکسان داشته باشند. جنگو اولین قالبی که پیدا کند را استفاده میکند.
- وقتی دو اپلیکیشن مدیریت (admin) سفارشی داشته باشند.
- وقتی وابستگی بین اپلیکیشنها وجود داشته باشد. مثلاً اپ A به مدل اپ B نیاز دارد. در این صورت اپ B باید بالاتر قرار بگیرد.
برای DRF چه قانونی رعایت کنیم؟
برای rest_framework، جای خاصی الزامی نیست. اما یک عرف رایج وجود دارد:
- اپهای خود جنگو (django.contrib.*) در بالا
- اپهای شخص ثالث (مثل rest_framework) در وسط
- اپهای خودتان در پایین
این ترتیب خوانایی فایل را بیشتر میکند. اشکالی ندارد اگر rest_framework را پایینتر قرار دهید. کار DRF مختل نمیشود.
یک نکته برای آینده
بعضی کتابخانههای جانبی DRF مثل rest_framework.authtoken برای احراز هویت توکن نیاز به اضافه شدن جداگانه دارند. آن موقع ممکن است ترتیب کمی مهم شود. در درس احراز هویت به آن میرسیم. فعلاً همین یک خط کافی است.
تنظیمات اولیه DRF در settings.py (اختیاری اما مفید)
DRF بدون هیچ تنظیم اضافهای کار میکند. اما با چند خط کد در settings.py میتوانید رفتار پیشفرض آن را مطابق نیاز خود تغییر دهید. این تنظیمات اجباری نیستند. بعداً هر زمان خواستید میتوانید برگردید و تغییرشان دهید.
تمام این تنظیمات داخل یک دیکشنری به نام REST_FRAMEWORK در settings.py قرار میگیرند.
تنظیم DEFAULT_RENDERER_CLASSES برای JSON محض
رندررها مشخص میکنند پاسخ API به چه قالبی تبدیل شود. به طور پیشفرض DRF دو رندرر دارد: یکی برای JSON و دیگری برای Browsable API (صفحه HTML).
در محیط تولید (سرور زنده)، معمولاً نیازی به صفحه HTML ندارید. فرستادن آن حجم پاسخ را زیاد میکند. میتوانید فقط رندرر JSON را فعال نگه دارید:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
]
}
با این تنظیم، وقتی آدرس API را در مرورگر باز کنید، دیگر صفحه زیبای Browsable API را نمیبینید. فقط یک صفحه خالی با متن JSON میبینید.
برای محیط توسعه، بهتر است این تنظیم را نکنید. Browsable API در حین کدنویسی خیلی کمک میکند.
تنظیم DEFAULT_PARSER_CLASSES
پارسرها مشخص میکنند DRF داده ورودی را چطور تفسیر کند. مثلاً وقتی کاربر JSON میفرستد، DRF باید آن را بخواند.
تنظیم پیشفرض DRF عالی است و نیازی به تغییر ندارد:
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
]
}
این سه پارسر به ترتیب اجازه میدهند: JSON، فرمهای معمولی، و فرمهای دارای فایل (آپلود) دریافت کنید.
تنها زمانی این تنظیم را تغییر میدهید که بخواهید فرمت خاصی مثل XML یا YAML را هم پشتیبانی کنید. برای بیشتر پروژهها، همان تنظیم پیشفرض کافی است.
معرفی DEFAULT_PERMISSION_CLASSES (دسترسی پیشفرض)
این مهمترین تنظیم امنیتی DRF است. مشخص میکند به طور پیشفرض誰 اجازه دسترسی به APIها را دارد.
تنظیم پیشفرض DRF این است:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
AllowAny یعنی هر کس بدون هیچ محدودیتی میتواند به API دسترسی داشته باشد. حتی بدون احراز هویت.
برای بسیاری از پروژهها این گزینه امن نیست. مخصوصاً وقتی API شما دادههای خصوصی کاربران را مدیریت میکند.
یک جایگزین امنتر:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
IsAuthenticated یعنی فقط کاربرانی که وارد شدهاند (لاگین کردهاند) میتوانند به API دسترسی داشته باشند.
نکته مهم
این تنظیم فقط سطح دسترسی پیشفرض را تعیین میکند. همچنان میتوانید روی هر ویو جداگانه سطح دسترسی متفاوتی تعریف کنید. مثلاً صفحه اصلی سایت با AllowAny کار کند، اما صفحه پروفایل کاربر فقط با IsAuthenticated.
در درس احراز هویت، این مفاهیم را کاملتر توضیح میدهیم. فعلاً اگر مطمئن نیستید، همین تنظیم پیشفرض (AllowAny) را حفظ کنید تا در کارهای عملی اولیه به مشکل نخورید.
یک نمونه کامل از تنظیمات پیشنهادی برای مرحله توسعه:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
],
}
این تنظیم ساده را میتوانید از حالا به settings.py اضافه کنید. بعداً در درسهای پیشرفته، مقادیر را به مرور تکمیل میکنیم.
تنظیم مسیر (URL) اصلی برای API - آمادهسازی برای درسهای بعد
حالا نوبت به اضافه کردن path('api/', include('myapp.urls')) در urls.py اصلی پروژه رسیده است. بعد از اینکه DRF نصب و تنظیم شد، باید مسیری برای دسترسی به APIها تعریف کنیم. این کار در فایل urls.py اصلی پروژه انجام میشود.
فایل urls.py را در پوشه پروژه (کنار فایل settings.py) باز کنید. کد زیر را به لیست urlpatterns اضافه کنید:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapp.urls')), # myapp نام اپلیکیشن شماست
]
توجه کنید که تابع include را هم از django.urls وارد کردیم.
با این کار، هر آدرسی که با api/ شروع شود، به فایل urls.py داخل اپلیکیشن myapp ارجاع داده میشود.
مرحله بعدی
باید داخل اپلیکیشن myapp یک فایل urls.py بسازید (اگر نیست) و مسیرهای مربوط به ویوهای DRF را در آن تعریف کنید. این کار را در درسهای بعدی انجام میدهیم. فعلاً فقط مسیر اصلی را آماده کردهایم.
چرا بهتر است همه APIها زیر آدرس /api/ قرار بگیرند؟
این کار یک قرارداد استاندارد در دنیای وب است. چند دلیل مهم دارد:
جداسازی از صفحات معمولی
وبسایت شما، هم صفحات HTML معمولی دارد (مثل صفحه اصلی، درباره ما، تماس با ما) و هم API. اگر همه APIها زیر api/ باشند، جدا کردن آنها از بقیه آدرسها راحت است.
مثلاً:
- /about/ یک صفحه HTML معمولی
- /api/products/ یک اندپوینت API
مدیریت آسان دسترسیها
بسیاری از ابزارهای امنیتی و فایروالها میتوانند بر اساس الگوی آدرس تصمیم بگیرند. مثلاً همه آدرسهای زیر api/ نیاز به توکن دارند. اما آدرسهای عادی سایت نیاز ندارند.
استفاده از پروکسی معکوس (Reverse Proxy)
اگر از سرورهایی مثل Nginx استفاده میکنید، میتوانید همه درخواستهای api/ را به یک سرور خاص (مثلاً سرور جنگو) و بقیه درخواستها را به سرور دیگر (مثلاً برای فایلهای استاتیک) هدایت کنید.
خوانایی و نگهداری آسان
وقتی تیم توسعه بزرگ میشود، همه میدانند آدرسهایی که با api/ شروع میشوند مربوط به DRF هستند. بقیه آدرسها مربوط به ویوهای معمولی جنگو. این شفافیت در پروژههای متوسط و بزرگ خیلی کمک میکند.
آمادگی برای نسخهبندی API
در آینده ممکن است بخواهید نسخههای مختلف API داشته باشید. با ساختار api/v1/، api/v2/ این کار خیلی راحت انجام میشود. بدون اینکه ساختار کلی سایت به هم بریزد.
یک نکته عملی
اجباری نیست از api/ استفاده کنید. میتوانید از هر اسم دیگری مثل v1/ یا backend/ هم استفاده کنید. اما api/ یک قرارداد جهانی است. برنامهنویسهای دیگر وقتی روی پروژه شما کار میکنند، انتظار همین را دارند.
در تمام درسهای بعدی، از همین الگو پیروی میکنیم: همه APIها زیر آدرس api/ قرار میگیرند.
بررسی نصب با یک ویو تستی ساده
بهترین راه برای اطمینان از نصب صحیح DRF، نوشتن یک ویو کوچک و دیدن نتیجه در مرورگر است. این کار را در چند دقیقه انجام میدهیم.
نوشتن یک ویو کوچک با APIView
اولین ویو DRF خود را مینویسیم. یک ویو ساده که فقط یک پیغام متنی برگرداند.
در اپلیکیشن مورد نظر (مثلاً myapp)، فایل views.py را باز کنید. کد زیر را اضافه کنید:
from rest_framework.views import APIView
from rest_framework.response import Response
class TestAPIView(APIView):
def get(self, request):
return Response({'message': 'DRF به درستی نصب و تنظیم شده است'})
این ویو فقط درخواست GET را میپذیرد و یک دیکشنری پایتون را به صورت JSON برمیگرداند. تابع Response کار تبدیل به JSON را انجام میدهد.
اتصال به URL
حالا باید این ویو را به یک آدرس متصل کنیم.
اگر فایل urls.py داخل اپلیکیشن myapp را ندارید، بسازید. یک فایل جدید به اسم urls.py در کنار views.py ایجاد کنید.
کد زیر را در آن قرار دهید:
from django.urls import path
from .views import TestAPIView
urlpatterns = [
path('test/', TestAPIView.as_view(), name='test-api'),
]
توجه کنید که از متد as_view() استفاده کردهایم. این متد کلاس ویو را به یک تابع قابل استفاده در URL تبدیل میکند.
حالا فایل urls.py اصلی پروژه را چک کنید. مطمئن شوید که مسیر api/ را به اپلیکیشن خود متصل کردهاید:
path('api/', include('myapp.urls')),
با این تنظیمات، ویو تستی ما در آدرس زیر در دسترس خواهد بود:
http://127.0.0.1:8000/api/test/
باز کردن Browsable API در مرورگر برای تأیید نصب صحیح
سرور توسعه جنگو را روشن کنید:
python manage.py runserver
حالا مرورگر خود را باز کنید و به آدرس زیر بروید:
http://127.0.0.1:8000/api/test/
چیزی که میبینید یک صفحه زیبا با عنوان "Test API View" است. این همان Browsable API است.
در صفحه، یک بخش آبی رنگ با عنوان "GET" میبینید. روی دکمه "GET" کلیک کنید. محتوای پاسخ در پایین صفحه نشان داده میشود:
{
"message": "DRF به درستی نصب و تنظیم شده است"
}
اگر این صفحه را میبینید، یعنی:
- DRF به درستی نصب شده است
- rest_framework به INSTALLED_APPS اضافه شده است
- مسیرها به درستی تنظیم شدهاند
- ویو شما کار میکند
اشکالات رایج در این مرحله
صفحه 404 دیدید؟ یعنی مسیر را اشتباه نوشتهاید. آدرس را چک کنید. حتماً api/test/ را وارد کنید، نه test/ تنها.
صفحه خطای 500 دیدید؟ احتمالاً نام کلاس یا متد را اشتباه وارد کردهاید. یا فراموش کردهاید سرور را بعد از تغییرات ریستارت کنید.
همه چیز سفید و بدون محتواست؟ شاید تنظیمات REST_FRAMEWORK را تغییر دادهاید و DEFAULT_RENDERER_CLASSES را فقط JSON گذاشتهاید. Browsable API برای نمایش به رندرر HTML نیاز دارد.
تبریک
نصب شما موفقیتآمیز بوده. از درس بعد، وارد مباحث اصلی DRF میشویم. اولین مدل را میسازیم، سریالایزر مینویسیم، و یک API کامل CRUD پیادهسازی میکنیم.
عیبیابی خطاهای رایج در نصب
نصب DRF معمولاً ساده است. اما گاهی خطاهایی پیش میآید. در این بخش سه خطای رایج را با هم بررسی میکنیم.
خطای ModuleNotFoundError: No module named 'rest_framework'
این خطا وقتی ظاهر میشود که پایتون نمیتواند DRF را پیدا کند.
دلیل اول: DRF نصب نشده است.
راه حل: دستور نصب را دوباره اجرا کنید:
pip install djangorestframework
دلیل دوم: محیط مجاز فعال نیست.
وقتی در ترمینال علامت (myenv) را نمیبینید، یعنی محیط مجاز فعال نیست. کتابخانههایی که نصب میکنید در محیط مجاز نمیروند.
راه حل: محیط را فعال کنید:
در ویندوز:
myenv\Scripts\activate
در مک و لینوکس:
source myenv/bin/activate
بعد از فعال شدن، دوباره نصب را امتحان کنید.
دلیل سوم: از ترمینال اشتباه استفاده میکنید.
اگر در VS Code یا PyCharm هستید، ممکن است ترمینال پیشفرض به محیط مجاز دیگری متصل باشد.
راه حل: ترمینال را ببندید و دوباره باز کنید. یا با دستور deactivate از محیط فعلی خارج شوید و دوباره محیط درست را فعال کنید.
فراموشی اضافه کردن به INSTALLED_APPS
نصب با pip فقط کتابخانه را در سیستم قرار میدهد. جنگو تا وقتی نام اپلیکیشن را در INSTALLED_APPS نبینید، آن را بارگذاری نمیکند.
نشانههای این خطا:
سرور روشن میشود اما Browsable API صفحه سفید یا خطا نشان میدهد.
هنگام استفاده از import rest_framework در کد، خطایی نمیگیرید اما قابلیتهای DRF کار نمیکنند.
راه حل:
فایل settings.py پروژه را باز کنید. به لیست INSTALLED_APPS بروید. خط زیر را اضافه کنید:
'rest_framework',
دقت کنید که بین اپهای قبلی کاما بگذارید. بعد از اضافه کردن، سرور را ریستارت کنید.
یک نکته مهم: گاهی افراد اشتباهی 'rest_framework' را به جای INSTALLED_APPS به MIDDLEWARE یا جای دیگر اضافه میکنند. فقط جای درست آن INSTALLED_APPS است.
تداخل نسخه جنگو و DRF
هر نسخه DRF با بازه خاصی از نسخههای جنگو سازگار است. اگر نسخهها با هم جور نباشند، ممکن است خطاهای عجیب ببینید.
نشانههای این خطا:
بعد از نصب، هنگام اجرای سرور خطای ImportError میگیرید.
بعضی از کلاسها یا توابع وجود ندارند (AttributeError).
مستندات DRF با چیزی که در کد شما کار میکند فرق دارد.
راه حل اول: نسخههای نصب شده را ببینید:
pip list | grep Django
pip list | grep djangorestframework
راه حل دوم: جدول سازگاری را چک کنید.
طبق مستندات رسمی DRF:
| نسخه DRF | نسخه جنگو سازگار |
| 3.15.x | 4.2, 5.0, 5.1 |
| 3.14.x | 3.2, 4.0, 4.1, 4.2 |
| 3.13.x | 2.2, 3.0, 3.1, 3.2 |
راه حل سوم: نسخه مشخصی را نصب کنید.
اگر جنگو شما 4.2 است، این دستور را بزنید:
pip install djangorestframework==3.15.2
اگر جنگو شما 3.2 است:
pip install djangorestframework==3.14.0
یک توصیه برای آینده
قبل از شروع پروژه جدید، همیشه آخرین نسخه پایدار جنگو و DRF را نصب کنید. در فایل requirements.txt حتماً شماره نسخه دقیق را قید کنید. این کار از بروز تداخل در آینده جلوگیری میکند.
pip freeze > requirements.txt
با این دستور، تمام کتابخانهها با شماره نسخه دقیق در فایل ذخیره میشوند.
جمعبندی و آماده شدن برای ساخت اولین مدل و سریالایزر
در این درس، محیط توسعه خود را برای کار با DRF آماده کردید.
djangorestframework را نصب کردید و دو کتابخانه جانبی markdown و django-filter را هم اضافه نمودید. rest_framework را به INSTALLED_APPS اضافه کردید تا جنگو آن را بشناسد.
با تنظیمات اولیه DRF آشنا شدید. دیدید که DEFAULT_PERMISSION_CLASSES تعیین میکند چه کسانی به API دسترسی داشته باشند. و یاد گرفتید چرا بهتر است همه APIها زیر آدرس /api/ قرار بگیرند.
یک ویو تستی با APIView نوشتید و آن را به URL متصل کردید. با باز کردن Browsable API در مرورگر، نصب صحیح را تأیید کردید. همچنین سه خطای رایج و راه حل هر کدام را مرور کردید.
از درس بعد، کار اصلی شروع میشود.
یک مدل ساده (مثلاً مدل مقاله یا محصول) میسازیم. برای آن سریالایزر مینویسیم. سپس ویوهای مربوط به CRUD را پیادهسازی میکنیم. در انتها همه چیز را در Browsable API تست خواهیم کرد.
برای درس بعد، این موارد را آماده داشته باشید:
یک پروژه جنگو با یک اپلیکیشن فعال
DRF نصب شده و در INSTALLED_APPS اضافه شده باشد
مسیر api/ در urls.py اصلی تنظیم شده باشد
اگر همه این مراحل را انجام دادهاید، برای قدم بعدی آماده هستید.