بناء API سريعة باستخدام FastAPI وPydantic خطوة بخطوة
يجمع FastAPI بين تعريف المسارات وقراءة البيانات وتوثيق API في أسلوب قريب من Python الحديثة. قوته لا تأتي من قصر الكود وحده، بل من استخدام type hints للتحقق من المدخلات وتوضيح شكل الاستجابة. سنبني مساراً يستقبل مهمة جديدة ويعيدها بعد التحقق من العنوان والأولوية، ثم نضيف استجابة منظمة. يستخدم المثال قائمة مؤقتة حتى نركز على شكل العقد بين العميل والخادم، ونوضح ما الذي يتغير عند ربط قاعدة بيانات حقيقية.
الفكرة الأساسية
يصف نموذج Pydantic الحقول التي يقبلها المسار وأنواعها وقواعدها الأساسية. يقرأ FastAPI جسم الطلب ويعيد خطأ واضحاً عندما يغيب حقل أو يصل بنوع غير مناسب. أما response_model فيحدد ما يخرج إلى العميل، وهو يمنع تسريب حقول داخلية بالخطأ. هذا الفصل بين الداخل والخارج يساعد على تغيير طريقة التخزين من دون كسر الواجهة.
مثال برمجي عملي
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class TaskInput(BaseModel):
title: str = Field(min_length=3, max_length=120)
priority: int = Field(default=1, ge=1, le=5)
class Task(TaskInput):
id: int
items = []
@app.post("/tasks", response_model=Task, status_code=201)
def create_task(payload: TaskInput):
task = Task(id=len(items) + 1, **payload.model_dump())
items.append(task)
return task
شرح المثال
يحتوي TaskInput على البيانات التي يسمح العميل بإرسالها، بينما يضيف Task المعرف الذي ينشئه الخادم. يرفض Field عنواناً قصيراً جداً أو أولوية خارج المجال المحدد قبل دخول الدالة. عند النجاح، تحول model_dump النموذج إلى قاموس ثم نعيد كائناً يطابق response_model. في مشروع حقيقي يجب توليد المعرف من قاعدة البيانات لا من طول القائمة.
ثبت fastapi وuvicorn، وضع الكود في main.py، ثم شغل uvicorn main:app --reload. افتح صفحة التوثيق التفاعلية وجرب طلباً صحيحاً وآخر ناقصاً. بعد ذلك أضف مسار القراءة، ثم انقل التخزين إلى طبقة مستقلة. لا تضع الاتصال بقاعدة البيانات داخل تعريف النموذج، لأن لكل طبقة مسؤولية مختلفة.
ابدأ من عقد واضح
قبل فتح المحرر، اكتب ما الذي يدخل إلى البرنامج وما الذي يجب أن يخرج منه. حدد أسماء الحقول وأنواعها والحالات التي تعني نجاحاً أو فشلاً. يساعد هذا العقد على كشف الالتباس مبكراً، ويجعل المثال قابلاً للتجربة من دون الاعتماد على التخمين. إذا تغيرت الفكرة، عدّل العقد أولاً ثم عد إلى التنفيذ.
قسّم العمل إلى خطوة يمكن تشغيلها ومراجعتها. قد تكون الخطوة دالة أو وحدة أو مساراً، بحسب التقنية. لا تخلط قراءة البيانات والتحقق منها وحفظها في كتلة واحدة إذا كان فصلها سيجعل الخطأ أوضح. وفي الوقت نفسه لا تنشئ طبقات كثيرة قبل أن تعرف ما الذي تحتاج إلى فصله.
تجارب ينبغي ألا تهملها
اختبر مدخلاً صحيحاً، ومدخلاً ناقصاً، وقيمة من نوع غير متوقع، ثم اختبر الحالة التي لا تعيد أي نتيجة. في المشاريع التي تتعامل مع شبكة أو ملفات، جرّب انقطاع المصدر وعودة استجابة بطيئة. اكتب النتيجة المتوقعة قبل التنفيذ، لأن المقارنة بين التوقع والواقع تساعدك على اكتشاف افتراضات مخفية.
- اجعل المثال قابلاً للتشغيل بعد إعداد قصير ومذكور.
- افصل الخطأ الذي يمكن للمستخدم إصلاحه عن خطأ الخادم.
- لا تكرر القاعدة نفسها في أكثر من دالة إذا كان يمكن وضعها في مكان واحد.
- راجع أثر التغيير على المستهلكين الحاليين للواجهة أو الوحدة.
ما الذي يجعل الحل عملياً؟
الحل العملي ليس الأطول، بل الذي يمكن قراءته وتعديله بعد انتهاء التجربة. اختر أسماء تشرح الغرض، واكتب تعليقات تشرح السبب لا ما يفعله السطر حرفياً. ضع الإعدادات المتغيرة في بيئة التشغيل، وحافظ على سجل واضح للتغييرات. عندما يعمل المثال، اطلب من شخص آخر أن يشرح خطواته؛ الأسئلة التي يطرحها ستكشف نقاطاً تحتاج إلى تبسيط.
خطوة ما بعد المثال
بعد تشغيل الكود، أضف حالة فشل واختباراً لها، ثم غيّر جزءاً واحداً في كل مرة. هذا الأسلوب يمنعك من فقدان مصدر المشكلة ويجعلك ترى أثر كل قرار. إذا احتجت إلى مكتبة جديدة، اقرأ حدودها قبل دمجها، وتأكد من أن فائدتها أكبر من كلفة إضافتها إلى المشروع.
أخطاء ينبغي تجنبها
لا تثق في التحقق الموجود في الواجهة الأمامية وحده، ولا تستخدم نموذجاً واحداً للمدخلات والاستجابة إذا كان سيعرض حقولاً داخلية. تجنب إعادة أخطاء Python الخام إلى العميل، ولا تنس تحديد رمز الحالة المناسب. كما يجب ضبط CORS والصلاحيات عند نشر API على نطاق عام.
خطوة تالية مناسبة
أضف نموذجاً لتعديل المهمة، ومساراً يعيد 404 عند غياب المعرف، ثم اكتب اختباراً باستخدام TestClient. جرّب أيضاً تعريف حقل اختياري، ولاحظ كيف يتغير التوثيق تلقائياً عندما تعدل النموذج.
فصل نموذج الطلب عن منطق FastAPI
من الأفضل ألا تجعل دالة المسار مسؤولة عن التحقق والتخزين وإرسال الإشعارات في الوقت نفسه. يمكن للنموذج أن يصف البيانات، بينما تتولى خدمة صغيرة إنشاء المهمة، وتتعامل طبقة التخزين مع قاعدة البيانات. هذا الفصل يجعل اختبار كل جزء أسهل، ويمنع ارتباط تفاصيل Pydantic بكل أجزاء التطبيق. راقب أيضاً شكل الأخطاء، فالمستخدم يحتاج إلى رسالة عملية، بينما يحتاج سجل الخادم إلى تفاصيل تشخيصية لا ينبغي كشفها في الاستجابة. وعندما تضيف إصداراً جديداً للواجهة، حافظ على النموذج القديم لفترة مناسبة أو قدم تحويلاً واضحاً للبيانات.
اكتب ملاحظة قصيرة عن القرار الذي اتخذته أثناء التجربة، وسجل ما قسته أو اختبرته بدلاً من الاكتفاء بانطباع عام. قارن النسخة البسيطة بالنسخة التي أضفت إليها هذه الخطوة، ثم اسأل هل تحسن الوضوح أو الأداء أو سهولة الصيانة. إذا لم يظهر أثر عملي، ارجع إلى التصميم الأبسط. هذه المراجعة تمنع تحول المثال التعليمي إلى تعقيد ثابت لا يخدم المستخدم.
خطة تطبيق عملية
بعد فهم موضوع «بناء API سريعة باستخدام FastAPI وPydantic خطوة بخطوة»، لا تنقل المثال إلى مشروع كبير دفعة واحدة. أنشئ مجلداً صغيراً، وثبت نسخة الأدوات التي ستستخدمها، ثم اكتب حالة نجاح واحدة يمكن تشغيلها من البداية إلى النهاية. احتفظ بالمدخل الذي استخدمته والنتيجة التي توقعتها، لأن ذلك يمنحك نقطة مقارنة عندما تغير الكود. إذا كان الموضوع يعتمد على خدمة أو قاعدة بيانات، جهز بيانات تجريبية لا تحمل معلومات حقيقية، واكتب طريقة تنظيفها بعد انتهاء الاختبار.
انتقل بعد ذلك إلى الحالات التي تسبب الالتباس. ماذا يحدث عندما تكون القيمة فارغة؟ كيف يتصرف البرنامج عند وصول نوع غير متوقع؟ هل تعود رسالة مفيدة إذا توقفت الخدمة الخارجية أو لم يجد التطبيق السجل المطلوب؟ اكتب إجابة لكل سؤال في اختبار أو ملاحظة قصيرة. لا تحاول معالجة كل احتمال في سطر واحد؛ فصل المسارات يجعل التصحيح أسهل ويمنع إخفاء المشكلة خلف استثناء عام.
من المفيد أن تقيس قبل التحسين وبعده. قد يكون القياس زمناً أو حجماً أو عدد استدعاءات أو نسبة أخطاء، بحسب طبيعة الموضوع. لا تعتمد على الانطباع وحده، ولا تقارن تشغيلين مختلفين من دون تثبيت الظروف قدر الإمكان. إذا لم يتحسن المؤشر، تراجع عن التغيير وابحث عن السبب بدلاً من إضافة طبقة أخرى. وبعد أن تستقر النتيجة، اكتب README قصيراً يوضح أمر التشغيل، المدخلات، المخرجات، وأهم قرار اتخذته أثناء البناء.
أخيراً، راجع حدود المثال. الكود التعليمي يشرح المفهوم، لكنه قد يحتاج في الإنتاج إلى صلاحيات، ومراقبة، واختبارات، وإدارة أسرار، وسياسة للتحديث. أضف ما يبرره الاستخدام الفعلي فقط. بهذه الطريقة تتعلم التقنية من دون أن تخلط بين نموذج صغير ونظام جاهز للمستخدمين.
مراجعة الاستجابة
بعد تشغيل المسار، جرّب إرسال جسم ناقص وقيمة خارج الحدود، ثم اقرأ الاستجابة من وجهة نظر العميل لا من وجهة نظر الخادم فقط. يجب أن يعرف المستهلك اسم الحقل الذي يحتاج إلى تعديله، وأن تبقى رسالة الخطأ مستقرة بما يكفي لبناء واجهة فوقها. احتفظ بالمخطط في مكان واضح، وحدثه عندما تضيف حقلاً أو تغير نوعاً. هذا الاهتمام بالعقد يوفر وقتاً أكبر من إضافة مسار جديد قبل التأكد من أن المسار الحالي مفهوم.
الخلاصة
أضف نموذجاً لتعديل المهمة، ومساراً يعيد 404 عند غياب المعرف، ثم اكتب اختباراً باستخدام TestClient. جرّب أيضاً تعريف حقل اختياري، ولاحظ كيف يتغير التوثيق تلقائياً عندما تعدل النموذج. يوضح هذا الموضوع كيف تتحول الفكرة النظرية إلى خطوات يمكن تشغيلها وفحصها.
ابدأ بتطبيق المثال على ملف صغير، ثم غيّر مدخلاً واحداً وراقب النتيجة. بعد ذلك أضف حالة فشل واكتب اختباراً لها، ثم انقل الفكرة إلى مشروعك الحقيقي بحذر. عندما تفهم سبب كل خطوة، ستستطيع تغيير الأدوات أو اللغة من دون فقدان المفهوم. البرمجة تتحسن بالمحاولات القصيرة والمراجعة المستمرة، لا بنسخ كود طويل من دون معرفة ما الذي يحميه أو ما الذي قد يكسره.