تكرار السؤال: …
الإجابة المختصرة
يستقبل خادم WSGI أو ASGI الطلب، فيمر عبر سلسلة الـ middleware بالترتيب المحدد في MIDDLEWARE، ثم يطابق URL resolver المسار مع view، ثم يعود الرد عبر الـ middleware بالترتيب العكسي.
الشرح
كل middleware دالة أو class تغلّف ما بعدها: الكود قبل get_response يعمل على الطلب، والكود بعده يعمل على الرد. لذلك الترتيب مهم: SecurityMiddleware أولًا، و SessionMiddleware قبل AuthenticationMiddleware لأن الأخير يقرأ الجلسة. يعمل Django مع ASGI لدعم views غير المتزامنة، لكن الـ ORM لا يزال متزامنًا في أجزاء كثيرة ويُستدعى عبر sync_to_async أو واجهاته غير المتزامنة مثل aget و acount.
مثال بالكود
import time
import logging
logger = logging.getLogger(__name__)
class TimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response # مرة واحدة عند الإقلاع
def __call__(self, request):
start = time.perf_counter()
response = self.get_response(request) # بقية السلسلة و الـ view
response["Server-Timing"] = f"app;dur={(time.perf_counter() - start) * 1000:.1f}"
return response
# settings.py
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"app.middleware.TimingMiddleware",
]أخطاء شائعة
- وضع middleware يعتمد على request.user قبل AuthenticationMiddleware.
- تنفيذ استعلامات ORM متزامنة داخل async view دون sync_to_async.
أسئلة متابعة
- ما الفرق بين WSGI و ASGI، وكيف يدير Flask سياق الطلب؟
- ما مشكلة N+1 في Django ORM وكيف تحلها بـ select_related و prefetch_related؟