ویژگی تصویر

معرفی کتابخانه fastapi-utils در پایتون

  /  پایتون   /  کتابخانه fastapi-utils در پایتون
بنر تبلیغاتی الف

fastapi-utils یک بسته جانبی سبک برای فریم‌ورک FastAPI است که چندین ابزار عملی و الگوهای متداول توسعه وب را به‌صورت آماده فراهم می‌کند. این کتابخانه مخصوصاً برای توسعه‌دهندگانی مفید است که می‌خواهند کدهای مرتب‌تر، خواناتر و قابل نگهداری‌تری بنویسند — به‌ویژه زمانی که پروژه بزرگ و پیچیده می‌شود.

چرا از fastapi-utils استفاده کنیم؟

  • ساده‌سازی الگوهای رایج مانند class-based views (CBV).
  • ابزارهای کوچک کمکی که تکرار کد را کاهش می‌دهند.
  • ادغام آسان با سیستم dependency که FastAPI ارائه می‌کند.
  • مناسب برای پروژه‌هایی که می‌خواهند ساختار مرتب‌تری برای مسیرها و کنترلرها داشته باشند.

ویژگی‌های کلیدی

  • cbv (Class-Based Views): امکان تعریف endpointها به صورت متدهای کلاس و اشتراک‌گذاری وابستگی‌ها بین متدها.
  • InferringRouter: جایگزین APIRouter با برخی بهبودها برای کار با cbv و تسهیل ثبت مسیرها.
  • چند ابزار جانبی کوچک که در برخی پروژه‌ها مفیدند (ساخت‌دهنده‌های پاسخ، کمک‌ به تست و…).

نصب

نصب بسیار ساده است و از pip قابل انجام است:

pip install fastapi-utils

این دستور پکیج را نصب می‌کند تا بتوانید از cbv و InferringRouter در پروژه FastAPI خود استفاده کنید.

مثال عملی: استفاده از cbv و InferringRouter

یکی از پرکاربردترین امکانات، امکان نوشتن کنترلرها به‌صورت کلاس است. مثال زیر نشان می‌دهد چگونه یک router و کلاس با وابستگی مشترک را تعریف کنیم.

from fastapi import Depends, FastAPI
from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter

app = FastAPI()
router = InferringRouter()

def get_db():
    # فرضی: بازگرداندن شیء اتصال به دیتابیس
    return {"conn": "db_connection"}

@cbv(router)
class ItemAPI:
    def __init__(self, db = Depends(get_db)):
        self.db = db

    @router.get("/items/{item_id}")
    def read_item(self, item_id: int):
        return {"item_id": item_id, "db": self.db}

app.include_router(router)

توضیح: در این مثال، با @cbv(router) کلاس ItemAPI به روتر متصل می‌شود. متد __init__ با استفاده از Depends یک وابستگی (در اینجا اتصال به دیتابیس) دریافت می‌کند و سپس همه متدهای مسیرِ کلاس می‌توانند به این وابستگی دسترسی داشته باشند. این روش خوانایی را افزایش می‌دهد و از تکرار dependency در هر مسیر جلوگیری می‌کند.

مزایا نسبت به تعریف تابعی معمولی

مسألهتعریف تابعیتعریف با cbv
اشتراک وابستگی‌هاهر تابع باید وابستگی را دوباره تعریف کندوابستگی‌ها در __init__ تعریف و بین متدها مشترک می‌شوند
سازماندهی کدتعداد زیادی تابع پراکندهگروه‌بندی مسیرها در کلاس‌های منطقی

بهترین روش‌ها و نکات کاربردی

  • وابستگی‌های حالت‌دار (مثلاً اتصال پایگاه داده) را در __init__ بگیرید، اما مراقب مدیریت context و همزمانی باشید.
  • از Pydantic models برای ورودی و خروجی endpointها استفاده کنید تا از مزایای اعتبارسنجی و مستندسازی خودکار FastAPI بهره‌مند شوید.
  • هرگاه عملیات I/O سنگین دارید (مثل پایگاه داده)، از متدهای async استفاده کنید تا مقیاس‌پذیری حفظ شود.
  • برای تست‌پذیری بهتر، وابستگی‌ها را به‌راحتی با override کردن در تست‌ها جایگزین کنید.

نسخه async و بهبود یافته

در مثال قبل می‌توان متد خواندن آیتم را به صورت async نوشت تا با کدهای غیرهمزمان بهتر کار کند:

from fastapi import Depends, FastAPI
from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter

app = FastAPI()
router = InferringRouter()

async def get_db():
    # فرضی: بازگرداندن شیء اتصال async به دیتابیس
    return {"conn": "async_db_connection"}

@cbv(router)
class ItemAPI:
    def __init__(self, db = Depends(get_db)):
        self.db = db

    @router.get("/items/{item_id}")
    async def read_item(self, item_id: int):
        # مثلاً await self.db.fetch_item(item_id)
        return {"item_id": item_id, "db": self.db}

app.include_router(router)

توضیح: این نسخه از get_db و متد read_item به‌صورت async تعریف شده‌اند تا با موتورهای async دیتابیس یا دیگر عملیات I/O همخوانی داشته باشند. استفاده از async به افزایش کارایی در بارهای همزمان کمک می‌کند.

موارد احتیاط و محدودیت‌ها

  • cbv کمک می‌کند کد منظم‌تری بنویسید، اما اگر وابستگی‌ها به‌صورت سراسری یا mutable باشند باید مراقب race condition و مسائل thread-safety باشید.
  • تا حد امکان منطق پیچیده کسب‌وکار را در سرویس‌ها یا لایه‌های جداگانه (نه مستقیماً در متدهای route) قرار دهید تا تست‌پذیری بهتر شود.
  • fastapi-utils ابزار کمکی است و همه نیازها را پوشش نمی‌دهد؛ گاهی استفاده از APIRouter استاندارد و توابع ساده مناسب‌تر است.

نمونه‌ی تست ساده با TestClient

مثالی از تست کردن endpoint نوشته‌شده با cbv با استفاده از TestClient:

from fastapi.testclient import TestClient

client = TestClient(app)

def test_read_item():
    response = client.get("/items/1")
    assert response.status_code == 200
    data = response.json()
    assert data["item_id"] == 1
    assert "db" in data

توضیح: این تست ساده نشان می‌دهد که چگونه می‌توانید endpointهای ساخته‌شده با fastapi-utils را مانند مسیرهای معمولی تست کنید. در تست‌های پیچیده‌تر می‌توان وابستگی get_db را با نسخه‌های mock جایگزین کرد.

نتیجه‌گیری و توصیه‌ها

fastapi-utils یک ابزار جمع‌وجور اما قدرتمند برای بهبود ساختار و کاهش تکرار در پروژه‌های FastAPI است. اگر پروژه شما بزرگ می‌شود و نیاز به سازمان‌دهی مسیرها و وابستگی‌ها دارید، استفاده از cbv و InferringRouter می‌تواند خوانایی و نگهداری کد را به‌طرز محسوسی افزایش دهد. با این حال، همواره توجه کنید که استفاده از این الگوها باید با درک محدودیت‌های همزمانی و نحوه مدیریت وابستگی‌ها همراه باشد.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: