بناء أول موقع باستخدام FastAPI

مقدمة إلى FastAPI

FastAPI هو إطار حديث وسريع (عالي الأداء) لبناء واجهات برمجة التطبيقات باستخدام Python، مستوحى من أطر عمل مثل Flask وDjango ولكنه مصمم لتوفير تجربة محسّنة لتطوير واجهات برمجة التطبيقات. من أبرز ميزاته قدرته على الاستفادة من تحديد نوع البينات في Python للتحقق التلقائي من البيانات، والقيام بالتسلسل والتوثيق، مما يجعل التطوير أكثر سلاسة وأقل عرضة للأخطاء.

فوائد FastAPI الرئيسية:

  • أداء عالي: مبني على Starlette وPydantic، ويتميز بأداء يقارب أداء Node.js وGo. يمكنه التعامل مع عدد كبير من الطلبات في الثانية بزمن استجابة منخفض.
  • سهل الاستخدام: تتيح بساطته للمطورين بناء واجهات برمجة التطبيقات بسرعة، مما يجعله ملائمًا للمبتدئين وقويًا للمطورين ذوي الخبرة.
  • توليد الوثائق تلقائيًا: ينشئ FastAPI تلقائيًا وثائق تفاعلية باستخدام Swagger UI وReDoc دون أي إعداد إضافي.
  • دعم البرمجة غير المتزامنة: البرمجة غير المتزامنة توفر دعمًا أصليًا لاستخدام Python مع كلمات async وawait، مما يساعد في إدارة التطبيقات التي تعتمد على عمليات الإدخال/الإخراج.

لماذا تختار FastAPI؟

يعد FastAPI مناسبًا للمشاريع التي تتطلب دورات تطوير سريعة دون التضحية بالقدرة على التوسع. يعمل بشكل جيد مع التطبيقات الفورية، والخدمات المصغرة، أو المشاريع التي تتطلب تحققًا معقدًا من البيانات.

التثبيت والإعداد

للبدء مع FastAPI، تحتاج إلى تثبيت Python 3.7+ على جهازك. إليك الخطوات اللازمة للتثبيت والإعداد:

  1. تثبيت FastAPI وUvicorn: FastAPI هو الإطار نفسه، بينما Uvicorn هو خادم ASGI اللازم لتشغيل التطبيق.
pip install fastapi uvicorn
  1. هيكل المشروع: لإنشاء مشروع بسيط، استخدم البنية التالية:

my_fastapi_project/
│
├── main.py       # ملف التطبيق الرئيسي
└── requirements.txt  # ملف لإدارة التبعيات (اختياري)
        
  1. إنشاء ملف main.py: اكتب تطبيق FastAPI بسيط:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}
        
  1. تشغيل التطبيق: استخدم Uvicorn لتشغيل ملف main.py:
uvicorn main:app --reload

سيكون التطبيق متاحًا افتراضيًا على الرابط http://127.0.0.1:8000.

إنشاء نقطة نهاية (Endpoint) أولى

إنشاء نقاط النهاية في FastAPI بسيط ويشبه الأنماط المستخدمة في أطر الويب الشائعة.


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "query": q}
    

الشرح:

  • @app.get("/items/{item_id}"): هذا النمط يربط المسار /items/{item_id} بالدالة read_item.
  • البارامترات (مدخلات الدالة): يقبض FastAPI المعاملات من المسار والتحقق من نوعها تلقائيًا.

توفر FastAPI وثائق تلقائية في:

تعريف معلمات المسار ومعلمات الاستعلام

يجعل FastAPI من السهل تحديد والتعامل مع معلمات المسار ومعلمات الاستعلام في مسارات API الخاصة بك، مع توفير تحقق من النوع وتكامل سهل من خلال تلميحات نوع Python.

معلمات المسار:

تعتبر معلمات المسار مقاطع من مسار URL ويتم تعريفها باستخدام الأقواس المتعرجة في الزخرفة. يستخرج FastAPI هذه المعلمات تلقائيًا ويتحقق منها.

python
@app.get("/users/{user_id}")
def read_user(user_id: int):
    return {"user_id": user_id}

الشرح: يتم توقع user_id في URL أن يكون عددًا صحيحًا. سيقوم FastAPI تلقائيًا بالتحقق من النوع ويرد بخطأ إذا تم تقديم نوع غير صالح.

معلمات الاستعلام:

تعتبر معلمات الاستعلام اختيارية وتأتي بعد الرمز ? في URL. يمكنك تعريفها كوسائط في الدالة مع القيم الافتراضية.

python
@app.get("/search")
def search_items(query: str = None, limit: int = 10):
    return {"query": query, "limit": limit}

الشرح: يمكن تمرير المعلمات query و limit كجزء من URL (على سبيل المثال، /search?query=books&limit=5). إذا لم يتم توفيرها، فإن query ستكون None وlimit ستساوي 10.

دمج معلمات المسار ومعلمات الاستعلام:

يمكنك استخدام كلا النوعين في نفس المسار:

python
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "query": q}

التعامل مع طلبات POST مع تحقق البيانات

يستفيد FastAPI من Pydantic للتحقق من البيانات وتحليلها. يتيح لك هذا التكامل تعريف هياكل الجسم المطلوبة كنماذج Pydantic، مما يضمن التحقق من صحة البيانات قبل تمريرها إلى دوال النقاط النهائية الخاصة بك.

تعريف نموذج Pydantic:

قم بإنشاء نموذج Pydantic لتمثيل هيكل البيانات المتوقع:

python
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str = None
    price: float
    in_stock: bool = True

استخدام النموذج في نقطة نهاية POST:

مرر نموذج Pydantic كمعامل إلى دالة المسار الخاصة بك:

python
@app.post("/items/")
def create_item(item: Item):
    return {"item_name": item.name, "price": item.price}

الشرح: عندما يتم إجراء طلب POST إلى /items/، سيقوم FastAPI بتحليل الحمولة JSON الواردة، والتحقق منها مقابل نموذج Item، وتمرير كائن item الذي تم تحليله إلى الدالة.

إذا فشلت الحمولة في التحقق، يقوم FastAPI تلقائيًا بإرجاع استجابة 422 Unprocessable Entity مع تفاصيل حول خطأ التحقق.

مثال على الطلب:

json
{
  "name": "Laptop",
  "price": 1200.50
}

مثال على الاستجابة:

json
{
  "item_name": "Laptop",
  "price": 1200.50
}

توثيق API وواجهة Swagger UI

تعد ميزة التوثيق التلقائي واحدة من أقوى ميزات FastAPI، حيث تسهل اختبار النقاط النهائية ومراجعة المسارات المتاحة دون إعداد إضافي.

واجهة Swagger UI:

يوفر FastAPI واجهة Swagger UI على http://127.0.0.1:8000/docs افتراضياً. تتيح هذه الواجهة:

  • رؤية جميع المسارات المتاحة ومعلمات الطلب المطلوبة/الاختيارية.
  • اختبار المسارات عن طريق إرسال الطلبات مباشرة من المتصفح.

ReDoc:

تعد ReDoc أداة أخرى متاحة للتوثيق على http://127.0.0.1:8000/redoc. توفر عرضاً أكثر تفصيلاً لهيكل الـ API.

تخصيص التوثيق:

يمكن تخصيص توثيق الـ API من خلال إضافة عنوان ووصف وإصدار:

app = FastAPI(
    title="My API",
    description="This is a simple API built with FastAPI",
    version="1.0.0"
)

فوائد التوثيق التلقائي:

  • اختبار سريع: يمكن للمطورين والفرق اختبار الـ API دون أدوات إضافية.
  • سهولة الاستخدام: تقلل الواجهة التفاعلية من الأخطاء عبر ضمان تمرير جميع البيانات المطلوبة بشكل صحيح.
  • تعزيز التعاون: يسهل على الفرق فهم الـ API والمساهمة فيه بفضل التوثيق الواضح والتفاعلي.

معالجة الأخطاء والاستجابات المخصصة

تعد معالجة الأخطاء بشكل جيد أمراً حيوياً لضمان بناء APIs موثوقة. يدعم FastAPI معالجة الأخطاء الشائعة تلقائياً ويسمح بتخصيص الردود لحالات محددة.

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

يقوم FastAPI تلقائياً بمعالجة بعض الأخطاء مثل مشكلات التحقق من النوع. على سبيل المثال، إذا تلقى معلمة مسار صحيحة بدلاً من سلسلة، يُعيد FastAPI استجابة 422 Unprocessable Entity.

إنشاء معالجة استثناءات مخصصة:

يمكنك استخدام فئة HTTPException لإنشاء استجابات مخصصة:

from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    if item_id not in range(1, 11):  # محاكاة تحقق من العنصر
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item_id": item_id}

الشرح: إذا كان item_id ليس بين 1 و10، يرفع FastAPI خطأ 404 مع الرسالة "Item not found".

نماذج استجابة مخصصة:

يمكنك تخصيص تنسيق الاستجابة باستخدام نماذج Pydantic لضمان هيكل موحد للردود.

from pydantic import BaseModel

class ResponseModel(BaseModel):
    success: bool
    data: dict

@app.get("/custom-response", response_model=ResponseModel)
def get_custom_response():
    return ResponseModel(success=True, data={"key": "value"})

البرمجة غير المتزامنة مع FastAPI

يدعم FastAPI البرمجة غير المتزامنة باستخدام async وawait، مما يسمح بمعالجة الطلبات المتزامنة بكفاءة. تعتبر هذه الميزة ضرورية للعمليات ذات طبيعة I/O مثل التعامل مع قواعد البيانات واستدعاء الشبكات.

المسارات المتزامنة وغير المتزامنة:

يمكنك تعريف المسارات باستخدام الدوال المتزامنة أو غير المتزامنة.

import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get("/async-example")
async def async_route():
    await asyncio.sleep(2)  # محاكاة مهمة I/O
    return {"message": "This route is asynchronous"}

الشرح: هذه الدالة تستخدم await لتتوقف مؤقتاً مما يسمح بتنفيذ مهام أخرى في نفس الوقت.

فوائد البرمجة غير المتزامنة:

  • زيادة عدد الاتصالات المتزامنة التي يمكن لـ API التعامل معها.
  • تحسين الأداء للمهام ذات طبيعة I/O.
  • مرونة في الجمع بين المسارات المتزامنة وغير المتزامنة في نفس التطبيق.

التعامل مع قواعد البيانات

يوفر FastAPI مرونة في التعامل مع قواعد البيانات، حيث يمكنك استخدام ORM مثل SQLAlchemy أو مكتبات حديثة مثل Tortoise-ORM للتكامل مع قواعد بيانات SQL. كما يمكن العمل مع قواعد بيانات NoSQL مثل MongoDB باستخدام مكتبات مثل Motor.

تكامل مع SQLAlchemy:

SQLAlchemy هو واحد من أشهر ORM في Python. يساعد في إدارة قاعدة البيانات باستخدام نماذج Python:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class Item(Base):
    __tablename__ = "items"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

Base.metadata.create_all(bind=engine)

مثال على دمج قاعدة البيانات مع FastAPI:

إضافة مسار للحصول على البيانات من قاعدة بيانات SQLite:

from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session

app = FastAPI()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/items/")
def read_items(db: Session = Depends(get_db)):
    items = db.query(Item).all()
    return items

اختبار تطبيقات FastAPI

الاختبار أمر ضروري لضمان استقرار التطبيق. يوفر FastAPI تكاملاً سهلاً مع مكتبة pytest واستخدام TestClient لاختبار المسارات.

إعداد اختبارات مع pytest:

يمكنك استخدام مكتبة fastapi.testclient لإنشاء اختبارات بسيطة:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello World"}

نصائح للاختبار:

  • استخدم اختبارات الوحدة لاختبار كل مسار على حدة.
  • اختبر حالات الحافة، مثل المدخلات غير الصالحة أو المعلمات المفقودة.
  • استخدم بيانات تجريبية لتجنب تغيير قاعدة البيانات الفعلية أثناء الاختبارات.

نشر تطبيقات FastAPI

يمكن نشر تطبيقات FastAPI باستخدام عدة تقنيات مثل Docker أو خدمات الاستضافة السحابية مثل Heroku وAWS.

نشر باستخدام Docker:

لجعل التطبيق قابلاً للنشر بسهولة، استخدم Docker لإدارة الحاويات:

# Dockerfile
FROM python:3.11
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

نشر على Heroku:

يمكنك نشر التطبيق على Heroku باستخدام إعدادات بسيطة:

  • أنشئ ملف Procfile يحتوي على:
web: uvicorn main:app --host 0.0.0.0 --port ${PORT:-5000}

خطوات إضافية:

  • تثبيت gunicorn لتحسين الأداء في الإنتاج.
  • استخدام تكوين بيئات مثل .env لإدارة المتغيرات الحساسة.

خاتمة وخطوات قادمة

لقد قمت ببناء واجهة برمجة تطبيقات API أساسية باستخدام FastAPI واستكشاف الجوانب الأساسية مثل التوجيه، التكامل مع قاعدة البيانات، التحقق من صحة البيانات، والاختبار. تابع مقال عن بناء RESTful API باستخدام FastAPI

إليك ملخص وما يمكنك القيام به لاحقًا:

ملخص:

  • تعلمت كيفية إنشاء مسارات أساسية والتعامل مع معلمات المسار/الاستعلام.
  • استكشفت التحقق من صحة البيانات باستخدام نماذج Pydantic ومعالجة طلبات POST.
  • اتصلت بقاعدة بيانات وقمت بتنفيذ عمليات CRUD الأساسية.
  • حصلت على فكرة عن كيفية كتابة وتشغيل الاختبارات لنقاط نهاية API.

خطوات قادمة:

  • التوثيق والتفويض: تعلم كيفية تنفيذ OAuth2 مع تدفق كلمة المرور لنقاط النهاية الآمنة.
  • المهام الخلفية: دمج المهام الخلفية للعمليات طويلة الأمد باستخدام دعم FastAPI المدمج.
  • نشر التطبيق: استكشاف نشر تطبيق FastAPI باستخدام أدوات مثل Docker ومنصات السحاب (مثل AWS، Azure).
  • ميزات متقدمة: الغوص أعمق في دعم WebSocket لتطبيقات الوقت الحقيقي، أو تنفيذ وسائط لمعالجة الطلبات المخصصة والتسجيل.

يوفر FastAPI إطارًا مرنًا وعالي الأداء لبناء تطبيقات الويب القابلة للتوسع. مع هذه المعرفة، أنت مستعد جيدًا لبناء وتوسيع المشاريع الواقعية.

حول المحتوى:

FastAPI هو إطار حديث وسريع (عالي الأداء) لبناء واجهات برمجة التطبيقات باستخدام Python، مستوحى من أطر عمل مثل Flask وDjango ولكنه مصمم لتوفير تجربة محسّنة لتطوير واجهات برمجة التطبيقات. من أبرز ميزاته قدرته على الاستفادة من تلميحات الأنواع في Python للتحقق التلقائي من البيانات، والقيام بالتسلسل والتوثيق، مما يجعل التطوير أكثر سلاسة وأقل عرضة للأخطاء.