🌐 Detecting your location…

كيفية بناء REST API باستخدام FastAPI

⏱️3 min read  ·  480 words

How to Build a REST API with FastAPI

أصبح FastAPI هو الخيار الافتراضي لواجهات برمجة تطبيقات Python الجديدة، وذلك لسبب وجيه: مستندات OpenAPI التلقائية، ودعم غير متزامن حقيقي، وطلب التحقق من الصحة المدعوم من Pydantic الذي يكتشف المدخلات السيئة قبل أن تمس منطق عملك. ينشئ هذا البرنامج التعليمي واجهة REST API عاملة من مجلد فارغ إلى خدمة CRUD مدعومة بقاعدة البيانات مع بنية جاهزة للمصادقة.

جدول المحتويات

إعداد المشروع

أنشئ بيئة افتراضية وقم بتثبيت الحزم الأساسية:

mkdir fastapi-todo && cd fastapi-todo
python3 -m venv venv
source venv/bin/activate

pip install fastapi uvicorn[standard] sqlmodel

uvicornهو خادم ASGI الذي يقوم بالفعل بتشغيل تطبيقك؛sqlmodelيجمع بين SQLAlchemy وPydantic لطبقة قاعدة بيانات تشارك النماذج مع مخططات API الخاصة بك.

طريقك الأول

إنشاءmain.py:

from fastapi import FastAPI

app = FastAPI(title="Todo API")

@app.get("/")
def read_root():
    return {"message": "Todo API is running"}

قم بتشغيله مع التحديث السريع:

uvicorn main:app --reload

زيارةhttp://127.0.0.1:8000وسترى استجابة JSON. زيارة/docsولديك بالفعل واجهة مستخدم Swagger تفاعلية – تم إنشاؤها من توقيعات وظيفتك فقط.

نماذج الطلب والاستجابة مع Pydantic

بدلاً من التحقق يدوياًrequest.json()بالنسبة للحقول المفقودة، حدد نموذجًا واترك FastAPI يتحقق من صحة الأمر نيابةً عنك:

from pydantic import BaseModel

class TodoCreate(BaseModel):
    title: str
    done: bool = False

@app.post("/todos")
def create_todo(todo: TodoCreate):
    return {"title": todo.title, "done": todo.done}

إرسال طلب مفقودtitleويقوم FastAPI بإرجاع خطأ منظم 422 تلقائيًا – لا حاجة إلى تعليمات برمجية إضافية. تعد طبقة التحقق هذه هي السبب الأكبر وراء ترحيل الفرق من Flask.

إضافة قاعدة بيانات باستخدام SQLModel

يتيح SQLModel لفئة واحدة أن تكون بمثابة جدول قاعدة البيانات ومخطط واجهة برمجة التطبيقات (API) الخاص بك:

from sqlmodel import SQLModel, Field, create_engine, Session

class Todo(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    title: str
    done: bool = False

engine = create_engine("sqlite:///todos.db")

def init_db():
    SQLModel.metadata.create_all(engine)

def get_session():
    with Session(engine) as session:
        yield session

اتصلinit_db()عند بدء التشغيل باستخدام معالج عمر FastAPI:

from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    init_db()
    yield

app = FastAPI(title="Todo API", lifespan=lifespan)

بناء نقاط نهاية CRUD كاملة

مع وجود تبعية النموذج والجلسة، تكون عمليات CRUD الأربع قصيرة وسهلة القراءة:

from fastapi import Depends, HTTPException
from sqlmodel import select

@app.post("/todos", response_model=Todo)
def create_todo(todo: Todo, session: Session = Depends(get_session)):
    session.add(todo)
    session.commit()
    session.refresh(todo)
    return todo

@app.get("/todos", response_model=list[Todo])
def list_todos(session: Session = Depends(get_session)):
    return session.exec(select(Todo)).all()

@app.get("/todos/{todo_id}", response_model=Todo)
def get_todo(todo_id: int, session: Session = Depends(get_session)):
    todo = session.get(Todo, todo_id)
    if not todo:
        raise HTTPException(status_code=404, detail="Todo not found")
    return todo

@app.put("/todos/{todo_id}", response_model=Todo)
def update_todo(todo_id: int, data: Todo, session: Session = Depends(get_session)):
    todo = session.get(Todo, todo_id)
    if not todo:
        raise HTTPException(status_code=404, detail="Todo not found")
    todo.title = data.title
    todo.done = data.done
    session.add(todo)
    session.commit()
    session.refresh(todo)
    return todo

@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: int, session: Session = Depends(get_session)):
    todo = session.get(Todo, todo_id)
    if not todo:
        raise HTTPException(status_code=404, detail="Todo not found")
    session.delete(todo)
    session.commit()
    return {"ok": True}

إشعارDepends(get_session)— نظام حقن تبعية FastAPI. يعملget_sessionلكل طلب، قم بتسليم النتيجة إلى وظيفتك، ثم قم بتنظيفها بعد ذلك. يتغير نفس النمط إلى المصادقة، وتحديد المعدل، والصفحات دون تكرار النموذج المعياري في كل معالج.

معالجة الأخطاء

HTTPExceptionيغطي معظم الحالات، ولكن بالنسبة للأخطاء الخاصة بالمجال، قم بتسجيل معالج استثناء مخصص حتى تظل الاستجابات متسقة عبر واجهة برمجة التطبيقات:

from fastapi.responses import JSONResponse
from fastapi import Request

class TodoLimitError(Exception):
    pass

@app.exception_handler(TodoLimitError)
def limit_handler(request: Request, exc: TodoLimitError):
    return JSONResponse(status_code=400, content={"error": "todo limit reached"})

المستندات التلقائية

كل مسار كتبته موثق بالفعل في/docs(اختيال) و/redoc(ReDoc)، الذي تم إنشاؤه من نماذج Pydantic وتلميحات الكتابة. أضف أوصافًا باستخدام سلسلة مستندية أوField(description=...)وتظهر في المخطط الذي تم إنشاؤه تلقائيًا – لا يوجد OpenAPI YAML منفصل للمحافظة عليه يدويًا.

يعمل في الإنتاج

للإنتاج، قم بتشغيل Uvicorn خلف Gunicorn مع العديد من العمال، أو استخدم وضع Uvicorn متعدد العمال:

gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

ضعه خلف Nginx أو موازن التحميل المُدار لإنهاء TLS، واستبدل SQLite بـ PostgreSQL عن طريق تغييرcreate_engineسلسلة الاتصال – لا تتغير واجهة برمجة تطبيقات SQLModel.

إذا كنت تقوم بإقران واجهة برمجة التطبيقات هذه بواجهة أمامية حديثة، فإنNext.js 15 ودليل PostgreSQLيغطي جانب العميل، وللتعرف على أساسيات المزامنة في JavaScript، راجعالمزامنة/الانتظار لدينا للغوص العميق.

الأسئلة الشائعة

هل FastAPI أسرع من Flask؟
إن دعم FastAPI غير المتزامن وأساس Starlette يجعله أسرع بشكل كبير في ظل التحميل المتزامن، خاصة بالنسبة لنقاط النهاية المرتبطة بالإدخال/الإخراج مثل مكالمات قاعدة البيانات أو طلبات واجهة برمجة التطبيقات الخارجية.

هل أحتاج إلى إلغاء المزامنة لكل مسار؟
لا، يعمل FastAPI بشكل متزامنdefالمسارات في تجمع مؤشرات الترابط تلقائيًا. استخدمasync defعند الاتصال بالمكتبات غير المتزامنة (برامج تشغيل قاعدة البيانات غير المتزامنة، httpx) للحصول على فوائد التزامن الحقيقية.

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

كيف أقوم بإضافة المصادقة؟
استخدم FastAPIOAuth2PasswordBearerمع حقن التبعية –get_current_userتقوم التبعية بالتحقق من صحة JWT وتتم إضافتها إلى أي مسار يحتاج إلى الحماية، مع الاحتفاظ بمنطق المصادقة في مكان واحد.

هل يستطيع FastAPI التعامل مع WebSockets؟
نعم وطنيا. تحديد الطريق مع@app.websocket("/ws")وasync defالمعالج الذي ينتظرwebsocket.receive_text()في حلقة.

جاهز للبناء؟

انسخ الكود أعلاه في مشروع جديد، ثم قم بتشغيلuvicorn main:app --reload، وابدأ في توسيع نموذج Todo بحقول مثل تواريخ الاستحقاق أو الأولوية. نمط حقن التبعية الذي استخدمته لجلسة قاعدة البيانات هو نفس النمط الذي ستصل إليه من خلال المصادقة والتخزين المؤقت وتحديد المعدل لاحقًا.

تب
فريق تكنبولس
تم النشر في 1 أغسطس 2026


MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা