مقدمة
من أهم المهارات التي يحتاجها مطور 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 =
ماذا يسمح لك أن تفعل؟
Pagination
إذا كان لدينا آلاف المنتجات، ليس من الجيد إرسالها كلها في Response واحد.
Pagination تسمح بتقسيم النتائج إلى صفحات صغيرة.
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS":
"rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 10,
}
بهذه الطريقة يمكن للعميل طلب جزء من النتائج في كل مرة.
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 والاختبارات والتوثيق ثم تعلم كيفية تجهيز المشروع للنشر.