بناء REST API باستخدام Django REST Framework

دليل عملي لفهم REST API وبناء API منظمة باستخدام Django REST Framework، بداية من Models وSerializers وصولًا إلى Authentication وPermissions.

بناء REST API باستخدام Django REST Framework
بناء واجهة REST API باستخدام Django REST Framework.

مقدمة

من أهم المهارات التي يحتاجها مطور Python Backend اليوم هي القدرة على بناء APIs يمكن لتطبيقات الويب أو تطبيقات الهاتف استخدامها.

بدل أن يكون Backend مسؤولًا فقط عن عرض صفحات HTML، يمكنه توفير API تتبادل البيانات مع أي Client قادر على إرسال واستقبال HTTP Requests.

وهنا يأتي دور Django REST Framework أو DRF، الذي يوفر مجموعة أدوات قوية لبناء REST APIs باستخدام Django.

ما هي REST API؟

REST هو أسلوب معماري لبناء خدمات تعتمد على HTTP وتتعامل مع الموارد Resources بطريقة منظمة.

مثلًا في متجر إلكتروني يمكن أن تكون لدينا موارد مثل:

  • Users
  • Products
  • Orders
  • Categories

ويمكن أن يكون لدينا Endpoint مثل:

GET /api/products/

لإرجاع قائمة المنتجات.

HTTP Methods

كل HTTP Method يعبر عادةً عن نوع معين من العمليات على الموارد.

Method الاستخدام مثال
GET جلب البيانات /api/products/
POST إنشاء مورد /api/products/
PUT تحديث كامل /api/products/1/
PATCH تحديث جزئي /api/products/1/
DELETE حذف مورد /api/products/1/

HTTP Status Codes

يجب أن يتعلم مطور Backend كيفية استخدام Status Codes المناسبة للتعبير عن نتيجة الطلب.

  • 200 — نجاح الطلب.
  • 201 — تم إنشاء مورد.
  • 204 — نجاح بدون محتوى.
  • 400 — طلب غير صحيح.
  • 401 — يحتاج إلى Authentication.
  • 403 — غير مسموح.
  • 404 — المورد غير موجود.
  • 500 — خطأ في الخادم.

تثبيت Django REST Framework

بعد إنشاء مشروع Django، يمكن تثبيت Django REST Framework باستخدام pip.

pip install djangorestframework

ثم نضيفه إلى INSTALLED_APPS.

INSTALLED_APPS = [

    # Django apps...

    "rest_framework",

    "products",
]

إنشاء Model

لنفترض أننا نبني API لإدارة المنتجات. نبدأ بإنشاء Model يمثل المنتج.

from django.db import models


class Product(models.Model):

    name = models.CharField(
        max_length=200
    )

    price = models.DecimalField(
        max_digits=10,
        decimal_places=2
    )

    stock = models.PositiveIntegerField(
        default=0
    )

    created_at = models.DateTimeField(
        auto_now_add=True
    )

    def __str__(self):
        return self.name

بعد ذلك ننفذ migrations لإنشاء البنية المناسبة في قاعدة البيانات.

python manage.py makemigrations

python manage.py migrate

ما هو Serializer؟

الـ Serializer مسؤول عن تحويل البيانات بين الشكل الذي يتعامل معه Python والشكل المناسب للإرسال عبر API، كما يمكنه التحقق من البيانات القادمة من العميل.

from rest_framework import serializers

from .models import Product


class ProductSerializer(
    serializers.ModelSerializer
):

    class Meta:

        model = Product

        fields = [
            "id",
            "name",
            "price",
            "stock",
            "created_at",
        ]
ملاحظة:

Serializer ليس مجرد أداة لتحويل البيانات، بل يمكن استخدامه أيضًا في Validation والتحكم في البيانات التي تدخل وتخرج من الـ API.

إنشاء API View

يمكن استخدام APIView لإنشاء Endpoint بطريقة واضحة والتحكم في HTTP Methods بشكل مباشر.

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import Product
from .serializers import ProductSerializer


class ProductListAPIView(APIView):

    def get(self, request):

        products = Product.objects.all()

        serializer = ProductSerializer(
            products,
            many=True
        )

        return Response(
            serializer.data
        )

عند إرسال GET Request إلى الـ Endpoint يمكن إرجاع قائمة المنتجات.

إنشاء Product من خلال API

يمكننا إضافة POST Method لإنشاء منتج جديد.

def post(self, request):

    serializer = ProductSerializer(
        data=request.data
    )

    if serializer.is_valid():

        serializer.save()

        return Response(
            serializer.data,
            status=201
        )

    return Response(
        serializer.errors,
        status=400
    )

هنا يقوم Serializer بالتحقق من البيانات قبل حفظها في قاعدة البيانات.

ربط الـ API بالـ URL

from django.urls import path

from .views import ProductListAPIView


urlpatterns = [

    path(
        "products/",
        ProductListAPIView.as_view(),
        name="product-list"
    ),

]

الآن يمكن للعميل إرسال Requests إلى:

/api/products/

Generic Views

يوفر DRF Generic Views تقلل كمية الكود الذي تحتاج إلى كتابته عندما تكون العمليات CRUD تقليدية.

from rest_framework.generics import (
    ListCreateAPIView
)

from .models import Product
from .serializers import ProductSerializer


class ProductListAPIView(
    ListCreateAPIView
):

    queryset = Product.objects.all()

    serializer_class = ProductSerializer

هذا يجعل الكود أقصر وأسهل عندما تتوافق احتياجات الـ Endpoint مع السلوك الذي توفره Generic View.

ViewSets

ViewSets توفر طريقة أخرى لتنظيم عمليات CRUD المرتبطة بمورد واحد.

from rest_framework.viewsets import ModelViewSet

from .models import Product
from .serializers import ProductSerializer


class ProductViewSet(ModelViewSet):

    queryset = Product.objects.all()

    serializer_class = ProductSerializer

ومع استخدام Router يمكن تقليل إعداد URLs بشكل كبير.

Routers

from rest_framework.routers import DefaultRouter

from .views import ProductViewSet


router = DefaultRouter()

router.register(
    "products",
    ProductViewSet
)

urlpatterns = router.urls

يقوم Router بإنشاء المسارات المناسبة للـ ViewSet وفق الإعدادات المستخدمة.

Validation

لا يجب أن تثق بأي بيانات يرسلها المستخدم إلى API. يجب التحقق منها قبل استخدامها أو حفظها.

class ProductSerializer(
    serializers.ModelSerializer
):

    def validate_price(self, value):

        if value <= 0:

            raise serializers.ValidationError(
                "السعر يجب أن يكون أكبر من صفر."
            )

        return value

بهذه الطريقة نستطيع وضع قواعد تحقق مخصصة للبيانات.

Authentication

Authentication يجيب عن سؤال: من هو المستخدم؟

في APIs يمكن استخدام آليات مختلفة للمصادقة حسب احتياجات النظام، مثل Session Authentication أو Token-based Authentication.

عند تصميم نظام حقيقي، يجب اختيار آلية المصادقة بناءً على طبيعة العملاء ومتطلبات الأمان.

Permissions

بعد معرفة هوية المستخدم، نحتاج إلى تحديد ما إذا كان مسموحًا له بتنفيذ العملية المطلوبة.

مثلًا يمكن السماح للمستخدم العادي بقراءة المنتجات، بينما يسمح فقط للمشرف بإضافة أو حذف المنتجات.

الفرق:

Authentication = من أنت؟
Authorization / Permissions = ماذا يسمح لك أن تفعل؟

Filtering والبحث

في التطبيقات الحقيقية يحتاج المستخدم غالبًا إلى البحث والفلترة وترتيب النتائج.

مثل البحث عن منتج بالاسم أو عرض المنتجات التي يقل سعرها عن قيمة معينة.

يمكن تنفيذ ذلك باستخدام Django ORM وأدوات الفلترة المناسبة في DRF.

كيف تصمم API جيدة؟

API الجيدة ليست مجرد API تعمل. يجب أن تكون مفهومة ومتوقعة وسهلة الاستخدام والصيانة.

  • استخدم أسماء واضحة للموارد.
  • استخدم HTTP Methods بشكل مناسب.
  • استخدم Status Codes الصحيحة.
  • تحقق من البيانات.
  • طبق Authentication وPermissions.
  • استخدم Pagination عند الحاجة.
  • وفر رسائل أخطاء واضحة.
  • وثق الـ API بشكل جيد.

تنظيم مشروع API

project/
│
├── config/
│
├── products/
│   ├── models.py
│   ├── serializers.py
│   ├── views.py
│   ├── urls.py
│   ├── permissions.py
│   └── tests.py
│
├── users/
│
├── orders/
│
├── manage.py
│
└── requirements.txt

فصل الملفات والمسؤوليات يجعل المشروع أسهل في التطوير والصيانة، خصوصًا عندما يبدأ عدد الـ Endpoints في الزيادة.

اختبار الـ API

لا يكفي أن تجرب الـ API يدويًا. مع نمو المشروع يصبح من المهم كتابة Tests تتأكد من أن النظام يعمل كما هو متوقع.

اختبر على الأقل:

  • إنشاء البيانات.
  • جلب البيانات.
  • تحديث البيانات.
  • حذف البيانات.
  • البيانات غير الصحيحة.
  • Authentication.
  • Permissions.

أخطاء شائعة

  • بناء API بدون فهم HTTP.
  • عدم التحقق من بيانات المستخدم.
  • إهمال Permissions.
  • إرجاع Status Codes غير مناسبة.
  • إرسال بيانات أكثر من المطلوب.
  • تجاهل Pagination في البيانات الكبيرة.
  • عدم اختبار Endpoints.
  • وضع كل منطق التطبيق في View واحدة.

تحدي عملي

بعد قراءة هذا المقال، حاول بناء API لمتجر إلكتروني صغير.

يجب أن تحتوي على:

  • Users API.
  • Products API.
  • Categories API.
  • Orders API.
  • Authentication.
  • Permissions.
  • Pagination.
  • Filtering.
  • Tests.
نصيحة:

لا تبدأ بكل هذه المميزات مرة واحدة. ابدأ بـ CRUD بسيط، ثم أضف كل ميزة تدريجيًا.

الخلاصة

Django REST Framework يوفر أدوات قوية لبناء REST APIs باستخدام Python وDjango.

لكن تعلم DRF لا يعني حفظ APIView أو ModelViewSet فقط. الأهم أن تفهم HTTP وREST وقواعد البيانات وAuthentication وPermissions وتصميم APIs.

ابدأ بمشروع صغير، ثم قم بتطويره تدريجيًا. كلما واجهت مشكلة جديدة، ستتعلم مفهومًا جديدًا يساعدك على الاقتراب من مستوى المشاريع الحقيقية.

الخطوة التالية:

بعد بناء API بسيطة، ركز على Authentication وPermissions والاختبارات والتوثيق ثم تعلم كيفية تجهيز المشروع للنشر.

شارك المقال