404 Not Found

404 Not Found


nginx

مقدمة في FastAPI — لماذا هو إطار الويب بايثون من الجيل التالي

إذا كانت Flask سكينيناً سويسرياً متعدد الاستخدامات، وDjango سيارة دفع رباعي مجهزة بالكامل، فإن FastAPI سيارة رياضية كهربائية — تسرع بسرعة، وتوفّر الطاقة، وتأتي مع لوحة قيادة مُولَّدة تلقائياً.

1. ما ستتعلمه


2. القصة الحقيقية لـ Alice

(1) نقطة الألم: إطار التزامن لا يستطيع التعامل مع ملايين الطلبات

Alice مهندسة واجهة خلفية تبني PriceTracker — واجهة برمجة تطبيقات SaaS لتتبع الأسعار لمنصة تجارة إلكترونية — تحتاج إلى التعامل مع استعلامات فورية لملايين أسعار المنتجات. بنت النموذج الأولي باستخدام Flask، لكن عندما تجاوزت الطلبات المتزامنة 1,000 QPS، تسبب نموذج WSGI المتزامن في اصطفاف كل طلب، وقفز زمن الاستجابة P99 إلى 3,000 مللي ثانية. اشتكى Bob (مهندس الواجهة الأمامية) من بطء تحميل الصفحة، وقال Charlie (DevOps) أن تكلفة التوسع الأفقي مرتفعة جداً.

(2) حل FastAPI

FastAPI مبني على بروتوكول ASGI غير المتزامن ويمكنه التعامل مع آلاف الاتصالات المتزامنة بعملية واحدة. تولّد تلميحات الأنواع تلقائياً توثيق OpenAPI وتتحقق من بيانات الطلب، لذلك لا تحتاج Alice لكتابة كود تحقق أو توثيق يدوياً.

PYTHON
from fastapi import FastAPI

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(product_id: int):
    # تلميح النوع يتحقق ويولّد التوثيق تلقائياً
    return {"product_id": product_id, "name": "Widget"}

(3) العائد

بعد الانتقال إلى FastAPI، ارتفع QPS لعقدة PriceTracker الواحدة من 500 إلى أكثر من 4,000، وانخفض زمن الاستجابة P99 إلى 50 مللي ثانية، وتحمّلت واجهة Bob الأمامية أسرع بـ 5 مرات، وانخفضت تكاليف خوادم Charlie بنسبة 60%.


3. ASGI وWSGI: التزامن هو المستقبل

(1) اختناقات WSGI المتزامنة

WSGI (واجهة بوابة خادم الويب) هو المعيار التقليدي لتطبيقات الويب بايثون؛ كل طلب يشغل خيطاً، وينتظر الخيط محجوباً عند حدوث عملية إدخال/إخراج (مثل استعلام قاعدة بيانات أو طلب شبكة).

100%
flowchart LR
    Client1[العميل 1] -->|طلب| WSGI[خادم WSGI]
    Client2[العميل 2] -->|طلب| WSGI
    Client3[العميل 3] -->|طلب| WSGI
    WSGI -->|الخيط 1| DB1[(قاعدة البيانات)]
    WSGI -->|الخيط 2| DB1
    WSGI -->|الخيط 3 - محجوب| DB1
البُعد WSGI ASGI
نموذج الاتصال طلب واحد، خيط واحد كوروتينات غير متزامنة، خيط واحد مع اتصالات متعددة
حد التزامن محدود بتجمع الخيوط (عادة 10-100) شبه غير محدود (الكوروتينات خفيفة)
انتظار الإدخال/الإخراج حجب الخيط غير محجوب، يتحول إلى كوروتين آخر
WebSocket غير مدعوم دعم أصلي
الخوادم النموذجية Gunicorn + Flask Uvicorn + FastAPI

(2) مزايا ASGI غير المتزامنة

ASGI (واجهة بوابة الخادم غير المتزامنة) هو امتداد غير متزامن لـ WSGI يدعم بناء async/await، مما يسمح لعملية واحدة بالتعامل مع آلاف الاتصالات المتزامنة.

PYTHON
import asyncio
import time

# نمط WSGI - يحجب الخيط
def sync_handler():
    time.sleep(1)  # الخيط محجوب لثانية واحدة
    return "done"

# نمط ASGI - غير محجوب
async def async_handler():
    await asyncio.sleep(1)  # حلقة الأحداث تتحول إلى مهام أخرى
    return "done"

(1) ▶ مثال: مقارنة التزامن مقابل التزامنية العالية غير المتزامنة

PYTHON
import asyncio
import time

async def fetch_price(product_id: int) -> dict:
    # محاكاة زمن إدخال/إخراج لقاعدة البيانات
    await asyncio.sleep(0.1)
    return {"product_id": product_id, "price": 9.99}

async def main():
    start = time.perf_counter()
    # 100 طلب متزامن - التزامنية تنتهي في ~0.1 ثانية
    results = await asyncio.gather(*[fetch_price(i) for i in range(100)])
    elapsed = time.perf_counter() - start
    print(f"Async: {len(results)} items in {elapsed:.2f}s")

asyncio.run(main())

الناتج:

TEXT
Execution Successful

Output:

TEXT
Async: 100 items in 0.10s

4. FastAPI مقابل Flask مقابل Django DRF

(1) التموضع ضمن منظومة الأطر

100%
flowchart LR
    FastAPI[FastAPI] --> Starlette[Starlette ASGI]
    Starlette --> Uvicorn[خادم Uvicorn]
    Uvicorn --> ASGI_Protocol[بروتوكول ASGI]
    FastAPI --> Pydantic[Pydantic V2]
    Flask2[Flask] --> Werkzeug[Werkzeug WSGI]
    Werkzeug --> Gunicorn[Gunicorn]
    Django2[Django DRF] --> Django_Core[نواة Django]
البُعد FastAPI Flask Django DRF
الأداء (TechEmpower RPS) ~40,000 ~1,200 ~800
دعم التزامنية async/await أصلي يتطلب إضافة دعم محدود
التوثيق التلقائي توليد تلقائي لـ OpenAPI يتطلب Flask-RESTX يتطلب drf-spectacular
التحقق من الأنواع تحقق تلقائي بـ Pydantic تحقق يدوي تعريف Serializer يدوي
منحنى التعلم منخفض (تلميحات الأنواع تعمل كتوثيق) منخفض مرتفع
حجم المشروع خدمات API صغيرة إلى متوسطة خدمات صغيرة مشاريع كاملة كبيرة

(2) لماذا FastAPI أنسب لـ PriceTracker

متطلبات PriceTracker مزايا FastAPI عيوب Flask
ملايين الاستعلامات في الثانية (QPS) تزامن عالي مع كوروتينات غير متزامنة تزامن منخفض مع حجب متزامن
بث أسعار فوري عبر WebSocket دعم أصلي غير مدعوم
توثيق API تلقائي لـ Bob توليد تلقائي لـ OpenAPI يتطلب إعداداً إضافياً
التحقق من بيانات الطلب تلقائي بـ Pydantic مصحّح تحقق مخصص
مصادقة JWT أدوات OAuth2 مدمجة تتطلب مكتبات طرف ثالث

(1) ▶ مثال: مقارنة ثلاث طرق لكتابة نفس API

PYTHON
# === FastAPI: تلميحات الأنواع = تحقق تلقائي + توثيق ===
from fastapi import FastAPI
from pydantic import BaseModel

class Product(BaseModel):
    name: str
    price: float

app = FastAPI()

@app.post("/products")
async def create_product(product: Product):
    return product  # تحقق تلقائي، توثيق تلقائي

الناتج:

TEXT
# تم تعريف الدالة بنجاح
PYTHON
# === Flask: تحقق يدوي، لا توثيق تلقائي ===
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/products", methods=["POST"])
def create_product():
    data = request.get_json()
    if not data or "name" not in data or "price" not in data:
        return jsonify({"error": "Invalid data"}), 400
    if not isinstance(data["price"], (int, float)):
        return jsonify({"error": "Price must be number"}), 400
    return jsonify(data)

5. تلميحات الأنواع تقود كل شيء

(1) القيمة الثلاثية لتلميحات الأنواع

يستخدم FastAPI تلميحات أنواع بايثون لإنجاز ثلاثة أمور دفعة واحدة: التحقق من البيانات، وال serialization/deserialization، وتوليد توثيق OpenAPI.

تلميح الأنواع الأطر التقليدية FastAPI
التحقق من البيانات if/else مكتوب يدوياً تلقائي بـ Pydantic
serialization لـ JSON json.dumps يدوي تلقائي عبر model_dump()
توثيق API Swagger YAML مكتوب يدوياً توليد تلقائي لـ OpenAPI
الإكمال التلقائي في IDE لا يوجد استنتاج كامل للأنواع

(1) ▶ مثال: التحقق التلقائي بتلميحات الأنواع

PYTHON
from fastapi import FastAPI, Query
from typing import Optional

app = FastAPI()

@app.get("/prices")
async def search_prices(
    min_price: float = Query(0.0, ge=0, description="الحد الأدنى للسعر بالدولار"),
    max_price: float = Query(999999.0, le=999999, description="الحد الأقصى للسعر بالدولار"),
    category: Optional[str] = Query(None, max_length=50),
):
    return {"min_price": min_price, "max_price": max_price, "category": category}

الناتج:

TEXT
# تم تعريف الدالة بنجاح

(2) ▶ مثال: توثيق OpenAPI المُولَّد تلقائياً

PYTHON
# بعد تعريف نقطة النهاية أعلاه، قم بزيارة:
# http://localhost:8000/docs  -> Swagger UI
# http://localhost:8000/redoc -> ReDoc
# http://localhost:8000/openapi.json -> مخطط OpenAPI الخام

Output (مقتطف من /openapi.json):

TEXT
{
  "paths": {
    "/prices": {
      "get": {
        "summary": "Search Prices",
        "parameters": [
          {"name": "min_price", "in": "query", "schema": {"type": "number", "minimum": 0.0}}
        ]
      }
    }
  }
}

(2) دور Pydantic

Pydantic V2 هو محرك تحقق من البيانات لـ FastAPI؛ أُعيدت كتابة نواته بـ Rust، مما يجعله أسرع بـ 5 إلى 50 مرة من V1.

الميزة Pydantic V1 Pydantic V2
المحرك الأساسي Python Rust (pydantic-core)
سرعة التحقق المعيار المرجعي أسرع بـ 5-50 مرة
المُحقِّق @validator @field_validator/@model_validator
الإعداد class Config model_config = ConfigDict(...)
serialization .dict() .model_dump()

6. البنية الأساسية: Starlette + Pydantic

(1) بنية FastAPI ثلاثية الطبقات

FastAPI نفسه غلاف رقيق؛ قدراته الأساسية تأتي من Starlette (إطار ASGI) وPydantic (التحقق من البيانات).

الطبقة المكون المسؤوليات
طبقة التطبيق FastAPI تسجيل المسارات، حقن التبعيات، توليد OpenAPI
طبقة ASGI Starlette الوسائط، معالجة الطلب/الاستجابة، WebSocket
طبقة التحقق Pydantic التحقق من البيانات، serialization، وتحويل الأنواع
طبقة الخدمة Uvicorn خادم ASGI، إدارة حلقة الأحداث

(1) ▶ مثال: استخدام ميزات Starlette مباشرة في FastAPI

PYTHON
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse

app = FastAPI()

# وسيط Starlette يعمل بسلاسة مع FastAPI
app.add_middleware(CORSMiddleware, allow_origins=["*"])

# فئات استجابة Starlette تعمل أيضاً
@app.get("/health")
async def health_check():
    return JSONResponse({"status": "healthy"})

الناتج:

TEXT
# تم تعريف الدالة بنجاح

(2) ▶ مثال: استخدام نماذج Pydantic في FastAPI

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

class PriceCreate(BaseModel):
    product_id: int = Field(gt=0)
    price: float = Field(gt=0, description="السعر بالدولار")
    currency: str = Field(default="USD", max_length=3)

app = FastAPI()

@app.post("/prices")
async def create_price(data: PriceCreate):
    # تم التحقق من البيانات وتحليلها بالفعل بواسطة Pydantic
    validated = data.model_dump()
    return {"status": "created", "data": validated}

الناتج:

TEXT
# تم تعريف الدالة بنجاح

7. نظرة عامة على مشروع PriceTracker

(1) ماذا تحاول Alice بناءه؟

PriceTracker هو واجهة برمجة تطبيقات SaaS لتتبع الأسعار. تشمل ميزاته الأساسية:

وحدة الوظيفة نقطة نهاية API الوصف
إدارة المنتجات CRUD في /products ملايين سجلات المنتجات
تتبع الأسعار CRUD في /prices استعلامات وإشعارات أسعار فورية
مصادقة المستخدمين /auth/login، /auth/register مصادقة JWT برمزين
خطط الاشتراك Free/Pro/Enterprise صلاحيات SaaS متعددة المستأجرين
الاستيراد المجمع /import/csv استيراد غير متزامن لملفات CSV من 1,000 صف
إشعارات فورية WebSocket /ws/prices تنبيهات فورية لتغيير الأسعار
100%
flowchart LR
    Bob[Bob - الواجهة الأمامية] -->|HTTP/WebSocket| API[PriceTracker API]
    Charlie[Charlie - DevOps] -->|مراقبة| API
    API -->|استعلام| DB[(PostgreSQL)]
    API -->|تخزين مؤقت| Redis[(Redis)]
    API -->|مهمة| Celery[عامل Celery]
    Celery -->|جلب| External[مواقع خارجية]

(1) ▶ مثال: PriceTracker — نسخة عمل مصغّرة

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field
from typing import Optional

app = FastAPI(title="PriceTracker API", version="0.1.0")

class ProductCreate(BaseModel):
    name: str = Field(max_length=200)
    category: str = Field(max_length=100)
    base_price: float = Field(gt=0, description="السعر الأساسي بالدولار")

class ProductResponse(BaseModel):
    id: int
    name: str
    category: str
    base_price: float

PRODUCTS_DB: dict[int, dict] = {}
_counter = 0

@app.post("/products", response_model=ProductResponse)
async def create_product(product: ProductCreate):
    global _counter
    _counter += 1
    record = {"id": _counter, **product.model_dump()}
    PRODUCTS_DB[_counter] = record
    return record

@app.get("/products/{product_id}", response_model=ProductResponse)
async def get_product(product_id: int):
    if product_id not in PRODUCTS_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRODUCTS_DB[product_id]

الناتج:

TEXT
# تم تعريف الدالة بنجاح

8. مثال شامل

تكمن قوة FastAPI الأساسية في التحقق التلقائي وتوليد التوثيق المدفوع بتلميحات الأنواع. يوضح ما يلي نقطة نهاية كاملة لاستعلام الأسعار تدمج معاملات المسار ونماذج Pydantic ونماذج الاستجابة.

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI(title="PriceTracker Demo")

class PriceResponse(BaseModel):
    product_id: int = Field(gt=0)
    product_name: str
    price: float = Field(gt=0)
    currency: str = "USD"

PRICES_DB: dict[int, dict] = {
    1: {"product_id": 1, "product_name": "Widget", "price": 9.99},
    2: {"product_id": 2, "product_name": "Gadget", "price": 24.50},
}

@app.get("/products/{product_id}", response_model=PriceResponse)
async def get_price(product_id: int):
    if product_id not in PRICES_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRICES_DB[product_id]

الناتج:

TEXT
GET /products/1 → {"product_id":1,"product_name":"Widget","price":9.99,"currency":"USD"}
GET /products/99 → 404 Not Found

❓أسئلة شائعة

س هل FastAPI مناسب للمشاريع الكبيرة؟
ج نعم، كذلك. حقن التبعيات في FastAPI وتجميع المسارات ونظام الوسائط يدعم التطوير النمطي للمشاريع الكبيرة. شركات مثل Reddit وMicrosoft وNetflix تستخدمه في الإنتاج.
س هل يجب عليّ استخدام async/await؟
ج لا، لست مضطراً. يدعم FastAPI دوال العرض المتزامنة وغير المتزامنة معاً. لكن async يقدم أداءً أفضل في السيناريوهات الكثيفة الإدخال/الإخراج (مثل قواعد البيانات وطلبات الشبكة).
س ما العلاقة بين FastAPI وStarlette؟
ج FastAPI مبني على Starlette، وهو إطار ASGI. يبني FastAPI على Starlette بإضافة ميزات مثل التحقق بـ Pydantic وحقن التبعيات وتوليد OpenAPI تلقائياً.
س هل يجب عليّ استخدام Pydantic V2؟
ج FastAPI 0.100+ يستخدم Pydantic V2 افتراضياً. V2 نواته مُعاد كتابتها بـ Rust وأسرع بـ 5 إلى 50 مرة من V1، لذا نوصي باستخدام V2 مباشرة.
س هل يمكن لـ FastAPI أن يحل محل Django؟
ج يعتمد على حالة الاستخدام. FastAPI هو إطار API لا يتضمن ORM أو واجهة إدارة أو محرك قوالب. إذا كنت تحتاج فقط خدمات API، فـ FastAPI الخيار الأفضل؛ وإذا كنت تحتاج نظام CMS كامل، فـ Django أنسب.
س هل أحتاج لتعلم Flask قبل تعلم FastAPI؟
ج لا. نهج FastAPI المدفوع بتلميحات الأنواع يختلف تماماً عن نهج Flask، لذا تعلم FastAPI مباشرة أكثر كفاءة فعلاً ويساعد على تجنب الأفكار المسبقة المبنية على مفاهيم مشابهة.

📖ملخص


📝تمارين

  1. تمرين أساسي (الصعوبة: ⭐): ثبّت FastAPI وUvicorn، أنشئ نقطة نهاية GET تُرجع {"message": "Hello PriceTracker"}، وشغّلها باستخدام uvicorn. تلميح: pip install fastapi uvicorn
  2. مسألة متقدمة (الصعوبة ⭐⭐): أضف معامل المسار name إلى نقطة النهاية، أرجع {"message": "Hello, {name}"}، وزُر /docs في متصفحك لعرض التوثيق المُولَّد تلقائياً. تلميح: @app.get("/hello/{name}")
  3. تحدٍ (الصعوبة: ⭐⭐⭐): أنشئ نموذج Pydantic باسم PriceInput يتضمن product_name: str وprice: float (يجب أن يكون > 0)، يستخدم نقطة نهاية POST لاستقبال البيانات، ويرجع نتيجة التحقق. تلميح: ورّث من BaseModel واستخدم Field(gt=0)

---|

Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%