404 Not Found

404 Not Found


nginx

توثيق API وتخصيص OpenAPI — إنشاء توثيق API احترافي

توثيق API مثل كتيب المنتج—بدونه، لن يستخدم العملاء (المطورون) منتجك؛ إذا كان مكتوبًا بشكل سيء، سيصوت العملاء بأقدامهم. إنشاء التوثيق الآلي هو السلاح السري لـ FastAPI، لكن التكوين الافتراضي هو مجرد نقطة البداية؛ التخصيص هو ما يميز المحترفين.

1. ما ستتعلمه


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

(1) نقطة الألم: التوثيق الافتراضي ليس احترافيًا بما يكفي

يستخدم توثيق PriceTracker API الخاص بـ Alice واجهة Swagger UI الافتراضية لـ FastAPI، حيث تكون جميع نقاط النهاية مختلطة بدون تجميع، لذا لا يمكن لـ Bob العثور على نقطة النهاية التي يحتاجها. لأسوأ من ذلك، يفتقر التوثيق إلى طلبات نموذجية، لذا لا يعرف Bob ما القيمة التي يجب إدخالها لحقل currency؛ لا يوجد إصدار لهيئات الطلب أو الاستجابة؛ ونقاط النهاية الجديدة والمهملة مختلطة معًا.

(2) حلول تخصيص OpenAPI

يسمح FastAPI بالتخصيص العميق لتوثيق OpenAPI—بما في ذلك تجميع العلامات، وقيم العينات، وعلامات الإهمال، والمخططات المخصصة—تحويل توثيق API من مجرد قابل للقراءة إلى قابل للاستخدام.

(3) العائد

يمكن لـ Bob ببساطة فتح التوثيق لتحديد موقع نقاط النهاية بسرعة حسب العلامة (Products/Prices/Auth). قيم العينات تزيل الحاجة للتخمين عند تقديم الطلبات، ونقاط النهاية المهملة محددة باللون الرمادي لمنع الاستخدام العرضي. نتيجة لذلك، ارتقت جودة التوثيق من مستوى مرجع داخلي إلى مستوى إصدار عام.


3. تكوين Swagger UI و ReDoc

(1) عملية إنشاء OpenAPI

100%
flowchart LR
    A[مسارات FastAPI] --> B[نماذج Pydantic]
    B --> C[مخطط OpenAPI 3.1]
    C --> D[Swagger UI /docs]
    C --> E[ReDoc /redoc]
    C --> F[JSON خام /openapi.json]

(1) ▶ مثال: تكوين توثيق على مستوى تطبيق FastAPI

PYTHON
from fastapi import FastAPI

app = FastAPI(
    title="PriceTracker API",
    description="""
    ## PriceTracker SaaS API
    
    خدمة تتبع أسعار التجارة الإلكترونية لمراقبة أسعار المنتجات بمستوى الملايين.
    
    ### (1) المصادقة
    جميع نقاط النهاية المحمية تتطلب رمز Bearer يتم الحصول عليه من `/auth/login`.
    
    ### (2) حدود المعدل
    - مجاني: 100 طلب/دقيقة
    - Pro: 1000 طلب/دقيقة
    - Enterprise: غير محدود
    """,
    version="1.0.0",
    terms_of_service="https://pricetracker.example.com/terms",
    contact={
        "name": "PriceTracker Support",
        "url": "https://pricetracker.example.com/support",
        "email": "support@pricetracker.example.com",
    },
    license_info={
        "name": "MIT License",
        "url": "https://opensource.org/licenses/MIT",
    },
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json",
)

الناتج:

TEXT
# التنفيذ ناجح

(3) ▶ مثال: تخصيص معلمات Swagger UI

PYTHON
app = FastAPI(
    swagger_ui_parameters={
        "persistAuthorization": True,  # الاحتفاظ بالمصادقة بين تحديثات الصفحة
        "displayRequestDuration": True,  # عرض مدة الطلب
        "filter": True,  # تمكين فلتر البحث
        "syntaxHighlight.theme": "monokai",  # سمات تمييز الكود
        "defaultModelsExpandDepth": 1,  # توسيع النماذج بمستوى عمق واحد
        "defaultModelExpandDepth": 1,
    }
)

الناتج:

TEXT
# التنفيذ ناجح
المعلمة الافتراضي الوصف
persistAuthorization False الاحتفاظ بالمصادقة عند تحديث الصفحة
displayRequestDuration False عرض مدة الطلب
filter False تمكين فلتر البحث
defaultModelsExpandDepth 1 عمق توسيع النموذج
syntaxHighlight.theme "agate" سمات تمييز الكود

4. تجميع العلامات وعلامات الإهمال

(1) العلامات: نقاط النهاية المجمعة

(1) ▶ مثال: تعريف العلامات

PYTHON
from fastapi import FastAPI, APIRouter

tags_metadata = [
    {
        "name": "auth",
        "description": "عمليات المصادقة. تسجيل الدخول، التسجيل، تحديث الرمز.",
    },
    {
        "name": "products",
        "description": "إدارة المنتجات. عمليات CRUD للمنتجات المتتبعة.",
    },
    {
        "name": "prices",
        "description": "بيانات الأسعار. الاستعلام، الاستيراد، وتتبع تغييرات الأسعار.",
    },
    {
        "name": "admin",
        "description": "عمليات المسؤول. تتطلب دور مسؤول.",
    },
]

app = FastAPI(
    title="PriceTracker API",
    openapi_tags=tags_metadata,
)

الناتج:

TEXT
# التنفيذ ناجح

(2) ▶ مثال: تعيين العلامات لنقاط النهاية

PYTHON
@app.post("/auth/login", tags=["auth"])
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    ...

@app.get("/api/v1/products", tags=["products"])
async def list_products():
    ...

@app.post("/api/v1/prices", tags=["prices"])
async def create_price():
    ...

@app.get("/api/v1/admin/stats", tags=["admin"])
async def admin_stats():
    ...

الناتج:

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

(3) ▶ مثال: تحديد نقطة نهاية كمهملة

PYTHON
@app.get(
    "/api/v1/products/{product_id}/history",
    tags=["prices"],
    deprecated=True,
    summary="[مهمل] استخدم GET /prices?product_id={id} بدلاً من ذلك",
)
async def get_price_history_deprecated(product_id: int):
    """هذه نقطة نهاية مهملة. استخدم نقطة نهاية الأسعار مع فلتر product_id."""
    ...

الناتج:

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

5. قيم العينات وقوالب الاستجابة

(1) json_schema_extra و examples

(1) ▶ مثال: قيم عينات لنماذج Pydantic

PYTHON
from pydantic import BaseModel, Field

class ProductCreate(BaseModel):
    name: str = Field(
        min_length=1, max_length=200,
        description="اسم عرض المنتج",
        examples=["Wireless Mouse", "USB-C Hub", "Mechanical Keyboard"],
    )
    category: str = Field(
        max_length=100,
        description="فئة المنتج",
        examples=["electronics", "clothing", "food"],
    )
    base_price: float = Field(
        gt=0,
        description="السعر الأساسي بالدولار",
        examples=[9.99, 49.99, 199.99],
    )

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "name": "Wireless Mouse",
                    "category": "electronics",
                    "base_price": 29.99,
                }
            ]
        }
    }

الناتج:

TEXT
# التنفيذ ناجح

(2) ▶ مثال: مثال استجابة على مستوى نقطة النهاية

PYTHON
from fastapi import FastAPI
from fastapi.responses import JSONResponse

@app.post(
    "/api/v1/products",
    response_model=ProductResponse,
    status_code=201,
    summary="إنشاء منتج جديد",
    description="إنشاء منتج جديد في قاعدة بيانات PriceTracker.",
    responses={
        201: {
            "description": "تم إنشاء المنتج بنجاح",
            "content": {
                "application/json": {
                    "example": {
                        "id": 1,
                        "name": "Wireless Mouse",
                        "category": "electronics",
                        "base_price": 29.99,
                    }
                }
            },
        },
        401: {"description": "المصادقة مطلوبة"},
        403: {"description": "صلاحيات غير كافية"},
        422: {"description": "خطأ في التحقق"},
    },
)
async def create_product(product: ProductCreate):
    ...

الناتج:

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

6. مخطط OpenAPI مخصص

(1) generate_unique_id_function

(1) ▶ مثال: إنشاء معرف نقطة نهاية مخصص

PYTHON
from fastapi import FastAPI

def custom_generate_unique_id(route):
    # التنسيق: {method}_{tag}_{path}
    tags = route.tags or ["default"]
    tag = tags[0]
    method = route.methods.pop() if route.methods else "GET"
    path = route.path.replace("/", "_").strip("_").replace("{", "").replace("}", "")
    return f"{method}_{tag}_{path}"

app = FastAPI(
    generate_unique_id_function=custom_generate_unique_id,
)

الناتج:

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

(2) مقارنة أفضل ممارسات التوثيق

البعد الافتراضي أفضل ممارسة
مجموعات نقاط النهاية بدون علامات حسب الوظيفة
نقاط النهاية المهملة مختلطة مع النقاط العادية deprecated=True علامة رمادية
مثال الطلب بدون examples + json_schema_extra
قوالب الاستجابة 200 فقط تغطية كاملة لـ 201/401/403/422
الوصف اسم دالة بسيط summary + description
معلومات المصادقة بدون صفحة رئيسية للتوثيق: شرح طرق المصادقة
الإصدار إصدار واحد إصدار مسار URL /api/v1/

❓ أسئلة شائعة

س ما الفرق بين Swagger UI و ReDoc؟
ج Swagger UI تفاعلي (يتيح لك اختبار واجهات API)، بينما ReDoc مصمم للقراءة (أكثر جاذبية بصريًا). نوصي بـ ReDoc للتوثيق الخارجي و Swagger UI للتطوير الداخلي.
س كيف يمكن إخفاء نقاط نهاية معينة حتى لا تظهر في التوثيق؟
ج عين include_in_schema=False:@app.get("/internal", include_in_schema=False). هذا مناسب لفحوصات الصحة الداخلية ونقاط نهاية المراقبة.
س هل يجب استخدام OpenAPI الإصدار 3.0 أم 3.1؟
ج FastAPI يُنشئ OpenAPI 3.1 بشكل افتراضي (الذي يدعم أحدث ميزات JSON Schema). إذا كنت بحاجة للتوافق مع أدوات قديمة، يمكنك تخفيض الإصدار في دالة openapi المخصصة.
س كيف أضيف CSS/JS مخصص إلى التوثيق؟
ج استخدم swagger_ui_parameters لتقديم URL لـ CSS، أو استخدم get_swagger_ui_html لتخصيص HTML بالكامل.
س ما الفرق بين قيم العينة والقيم الافتراضية؟
ج أمثلة "examples" هي لأغراض التوثيق ولا تؤثر على التحقق؛ "default" هي القيم الافتراضية الفعلية التي تؤثر على السلوك. يجب تعيين كليهما.
س كيف يجب تنظيم توثيق إصدارات API المتعددة؟
ج استخدم APIRouter(prefix="/api/v1") منفصل لكل إصدار وميز بين الإصدارات باستخدام العلامات. بدلاً من ذلك، أنشئ تطبيق FastAPI فرعي منفصل لكل إصدار.

📖 ملخص


📝 تمارين

  1. تمرين أساسي (الصعوبة ⭐): قم بتكوين توثيق على مستوى تطبيق FastAPI لـ PriceTracker—بما في ذلك العنوان والوصف ورقم الإصدار ومعلومات الاتصال—وأضف persistAuthorization=True لضمان احتفاظ Swagger UI بحالة المصادقة. تلميح: FastAPI(title=..., swagger_ui_parameters={...})
  2. تمرين متقدم (الصعوبة ⭐⭐): عرّف 4 علامات (auth/products/prices/admin)، عين العلامة الصحيحة لكل نقطة نهاية، حدد نقطة النهاية المهملة deprecated=True، وتحقق من أن نقاط النهاية مجمعة حسب العلامة في Swagger UI. تلميح: openapi_tags=[...] + tags=["products"]
  3. تحدي (الصعوبة ⭐⭐⭐): أضف مثال json_schema_extra كامل إلى ProductCreate، وأضف قوالب استجابة لرموز الحالة 201 و 401 و 403 و 422 (بما في ذلك محتوى نموذجي) إلى نقطة نهاية POST /products لتنفيذ generate_unique_id_function مخصص. تلميح: responses={201: {"content": {...}}} + generate_unique_id_function

---|

Web-Tutorial.com

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

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

100%