فصل ۱۸ — ساخت API با Django REST Framework

""

۱. مقدمه — چرا API بسازیم؟

APIهایی که ما می‌سازیم معمولاً برای این کارها استفاده می‌شوند:

  • اپلیکیشن موبایل (Android/iOS) پروژه‌مون از API ما داده بگیره
  • داده‌ها رو به سرویس‌های دیگر بدیم (مثلاً همکاری با یک مارکت‌پلیس)
  • جداسازی Frontend از Backend (مثلاً React یا Vue داده رو از API می‌گیره)

📌 تفاوت این فصل با فصل قبلی:

  • فصل ۱۷ → مصرف APIهای دیگر
  • فصل ۱۸ → ساخت API و ارائه داده به دیگران

۲. Django REST Framework چیست؟

Django REST Framework (یا DRF) یک فریمورک قدرتمند روی جنگو هست که:

  • کار با JSON رو ساده می‌کنه
  • احراز هویت، فیلتر، صفحه‌بندی، حقوق دسترسی رو راحت می‌کنه
  • به سرعت میشه CRUD API ساخت

📌 نصب DRF:

pip install djangorestframework

۳. ایجاد پروژه و پیکربندی اولیه DRF

فرض کنیم پروژه فروشگاه داریم.

settings.py

INSTALLED_APPS = [
    # اپ‌های جنگو
    'rest_framework',
    'store',  # اپلیکیشن فروشگاه ما
]

برای این فصل از قبل مدل Product داریم.


۴. مدل نمونه (Product)

# store/models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    description = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

📌 ما می‌خوایم این مدل رو به صورت JSON در API بدهیم.


۵. Serializers — تبدیل مدل به JSON

در DRF یک کلاس خاص به اسم Serializer داده‌های مدل رو به JSON تبدیل می‌کنه (و برعکس).

# store/serializers.py
from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'  # همه فیلدهای مدل

📌 ModelSerializer خودش فیلدها رو از مدل می‌خونه، نیازی نیست دستی تعریف کنیم مگر اینکه بخوایم شخصی‌سازی کنیم.


۶. اولین API ساده با DRF — Function-based View

# store/views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Product
from .serializers import ProductSerializer

@api_view(['GET'])
def product_list(request):
    products = Product.objects.all()
    serializer = ProductSerializer(products, many=True)
    return Response(serializer.data)

📌 many=True یعنی داریم یک لیست از اشیا رو سریالایز می‌کنیم.


۷. تنظیم URL برای API

# store/urls.py
from django.urls import path
from .views import product_list

urlpatterns = [
    path('api/products/', product_list, name='product_list')
]

۸. Test — نتیجه اولین API

وقتی /api/products/ رو باز کنیم، خروجی JSON می‌بینیم:

[
    {
        "id": 1,
        "name": "کفش ورزشی",
        "price": "50.00",
        "description": "مناسب دویدن",
        "created_at": "2025-09-27T10:00:00Z"
    },
    ...
]

۹. افزودن API برای جزئیات یک محصول

@api_view(['GET'])
def product_detail(request, pk):
    try:
        product = Product.objects.get(pk=pk)
    except Product.DoesNotExist:
        return Response({"error": "محصول یافت نشد"}, status=404)

    serializer = ProductSerializer(product)
    return Response(serializer.data)

۱۰. ساخت API CRUD کامل با CBV (Class-based Views) — ViewSet

DRF قابلیت‌های زیادی داره، یکی از مهم‌ترین‌هاش ViewSet هست که چند عملیات رو یکجا انجام می‌ده.

from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

۱۱. استفاده از Router برای تنظیم خودکار URLها

# store/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register(r'products', ProductViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

📌 با این کد، خودکار مسیرهای زیر ایجاد میشه:

  • /api/products/ → لیست + ایجاد محصول
  • /api/products/{id}/ → جزئیات + ویرایش + حذف

۱۲. افزودن Pagination (صفحه‌بندی) به API

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 5
}

📌 حالا /api/products/ به جای کل لیست، داده رو صفحه‌بندی می‌کنه:

{
    "count": 20,
    "next": "http://localhost:8000/api/products/?page=2",
    "previous": null,
    "results": [...]
}

۱۳. افزودن قابلیت جستجو و فیلتر

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'rest_framework.filters.SearchFilter',
        'rest_framework.filters.OrderingFilter'
    ],
    'SEARCH_PARAM': 'q',
}

# views.py
class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    search_fields = ['name', 'description']
    ordering_fields = ['price', 'created_at']

📌 حالا /api/products/?q=کفش جستجو میکنه، و /api/products/?ordering=-price مرتب‌سازی نزولی قیمت رو انجام میده.


۱۴. احراز هویت (Authentication)

برای حفاظت از API می‌تونیم روش‌های مختلف بذاریم:

  • Token Authentication
  • OAuth2 / JWT

نمونه Token Authentication:

pip install djangorestframework-authtoken
# settings.py
INSTALLED_APPS += ['rest_framework.authtoken']

REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = [
    'rest_framework.authentication.TokenAuthentication',
]

📌 الان برای درخواست باید Header:

Authorization: Token your_token_here

بفرستیم.


۱۵. مدیریت دسترسی (Permissions)

DRF می‌تونه تعیین کنه چه کسی می‌تونه چه کاری انجام بده.

from rest_framework.permissions import IsAuthenticated

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    permission_classes = [IsAuthenticated]

📌 الان فقط کاربر لاگین‌شده می‌تونه API رو استفاده کنه.


۱۶. سناریوی واقعی — API فروشگاه آنلاین

مسیرها:

  • /api/products/ → لیست همه محصولات (GET)، افزودن محصول (POST)
  • /api/products/{id}/ → جزئیات محصول (GET)، ویرایش (PUT/PATCH)، حذف (DELETE)
  • جستجو (?q=text)
  • مرتب‌سازی (?ordering=price یا ?ordering=-price)
  • صفحه‌بندی خودکار (?page=2)

مزایای این API:

  • میشه ازش توی یک اپ موبایل استفاده کرد
  • میشه به همکارها یا خدمات دیگه داد
  • همه‌چیز استاندارد و ساختاریافته است

۱۷. مشکلات رایج در DRF

مشکلعلتراه‌حل
JSON ناقص یا خالیسریالایزر فیلدها رو نپوشش دادهمطمئن شو fields = '__all__' یا دستی همه رو تعریف کردی
403 Permission Deniedکاربر مجوز نداره یا احراز هویت اشتباههبررسی permission_classes و Token
API کندQuery زیاد به دیتابیساستفاده از select_related یا prefetch_related

۱۸. بهترین روش‌ها (Best Practices)

  • استفاده از ViewSet + Router برای راحتی
  • اضافه کردن Pagination در همه APIها
  • احراز هویت مناسب (Token یا JWT)
  • استفاده از throttling برای جلوگیری از سوءاستفاده
  • نگه‌داری API Keys در .env
  • تست API با Postman یا ابزارهای مشابه

۱۹. نتیجه‌گیری فصل ۱۸

در این فصل یاد گرفتیم:

  • DRF رو نصب و پیکربندی کنیم
  • مدل رو با Serializer به JSON تبدیل کنیم
  • API CRUD کامل با ViewSet بسازیم
  • Pagination، جستجو، مرتب‌سازی، احراز هویت و مجوزها اضافه کنیم
  • سناریوی واقعی فروشگاه را به صورت API ارائه کنیم
محمد وب‌سایت

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *