مسار و Query Parameters في FastAPI
مقدمة: لماذا نحتاج path و query parameters؟
الفصل الأول: مقدمة: لماذا نحتاج إلى Path Parameters و Query Parameters؟
في الدرس السابق، تعلمنا كيفية إنشاء أول نقطة نهاية (endpoint) في FastAPI تعيد رسالة ثابتة. لكن في عالم تطبيقات الويب الحقيقية، نادراً ما نتعامل مع بيانات ثابتة. تخيل أنك تريد بناء API لإدارة المهام (Tasks API) – كيف ستتمكن من جلب مهمة محددة برقمها؟ أو كيف ستسمح للمستخدم بتصفية المهام حسب تاريخ معين؟ هنا يأتي دور معاملات المسار (Path Parameters) و معاملات الاستعلام (Query Parameters).
ببساطة، هذه المعاملات هي الطريقة التي نرسل بها بيانات ديناميكية إلى الـ API الخاص بنا. بدونها، سيكون كل endpoint ثابتاً ولا يمكنه التعامل مع طلبات مختلفة. في هذا الدرس، سنتعلم كيفية استخدام هذين النوعين من المعاملات لجعل API الخاص بنا تفاعلياً وقوياً.
ما هي Path Parameters؟
معاملات المسار (Path Parameters) هي أجزاء متغيرة من مسار URL نفسه. على سبيل المثال، في الرابط التالي:
https://example.com/items/42
الرقم 42 هو معامل مسار يمثل رقم العنصر الذي نريد الحصول عليه. في FastAPI، نحدد هذه المعاملات باستخدام الأقواس المتعرجة {} داخل مسار الـ endpoint.
مثال عملي: إنشاء Endpoint بمعامل مسار
لنقم بإنشاء endpoint بسيط يستقبل رقم مهمة ويعيد تفاصيلها. افتح ملف main.py الذي أنشأناه في الدرس السابق وأضف الكود التالي:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
@app.get("/tasks/{task_id}")
def read_task(task_id: int):
return {"task_id": task_id, "message": f"تم استلام المهمة رقم {task_id}"}
شرح الكود:
@app.get("/tasks/{task_id}"): هذا هو الـ decorator الذي يحدد أن هذا الـ endpoint يستجيب لطلبات GET على المسار/tasks/متبوعاً بقيمة متغيرة نسميهاtask_id.def read_task(task_id: int):: هنا نعرف دالة تأخذ معامل اسمهtask_idمن النوعint. FastAPI يقوم تلقائياً باستخراج القيمة من المسار وتحويلها إلى عدد صحيح.- الدالة تعيد قاموساً (dictionary) يحتوي على
task_idورسالة ترحيبية.
لتجربة الكود:
- شغل الخادم باستخدام الأمر:
uvicorn main:app --reload - افتح المتصفح على الرابط:
http://127.0.0.1:8000/tasks/5 - سترى النتيجة:
{"task_id":5,"message":"تم استلام المهمة رقم 5"}
/tasks/abc، سيعيد FastAPI خطأ تلقائياً لأننا حددنا أن task_id يجب أن يكون عدداً صحيحاً. هذا هو أحد فوائد استخدام type hints في Python مع FastAPI.
ما هي Query Parameters؟
معاملات الاستعلام (Query Parameters) هي أجزاء من URL تأتي بعد علامة الاستفهام ? وتكون على شكل أزواج مفتاح=قيمة (key=value). على سبيل المثال:
https://example.com/items?category=books&page=2
هنا category و page هما معاملات استعلام. في FastAPI، نحددها ببساطة كمعاملات اختيارية في دالة الـ endpoint.
مثال عملي: إضافة Query Parameters
لنقم بتوسيع مثالنا السابق. سنضيف إمكانية تصفية المهام حسب الحالة (مكتملة أم لا) أو حسب الكلمة المفتاحية في العنوان.
from fastapi import FastAPI
app = FastAPI()
# قاعدة بيانات وهمية (سنستبدلها لاحقاً بقاعدة بيانات حقيقية)
fake_tasks_db = [
{"id": 1, "title": "شراء حليب", "completed": False},
{"id": 2, "title": "قراءة كتاب", "completed": True},
{"id": 3, "title": "تعلم FastAPI", "completed": False},
]
@app.get("/tasks/{task_id}")
def read_task(task_id: int):
# البحث عن المهمة في القائمة
for task in fake_tasks_db:
if task["id"] == task_id:
return task
return {"error": "المهمة غير موجودة"}
@app.get("/tasks")
def list_tasks(completed: bool = None, keyword: str = None):
"""
تعيد قائمة بالمهام، مع إمكانية التصفية حسب:
- completed: إذا كان True تعيد المهام المكتملة، إذا كان False تعيد غير المكتملة
- keyword: تعيد المهام التي تحتوي على الكلمة المفتاحية في العنوان
"""
result = fake_tasks_db
if completed is not None:
result = [task for task in result if task["completed"] == completed]
if keyword:
result = [task for task in result if keyword.lower() in task["title"].lower()]
return result
شرح الكود:
@app.get("/tasks"): هذا endpoint جديد لاستعراض جميع المهام.def list_tasks(completed: bool = None, keyword: str = None):: نعرف معاملين اختياريين.completedمن نوعbool(قيمته الافتراضيةNoneتعني عدم التصفية)، وkeywordمن نوعstr.- داخل الدالة، نطبق منطق التصفية بناءً على القيم المستلمة.
لتجربة الكود:
- أعد تشغيل الخادم (إذا كان يعمل، سيتم إعادة التحميل تلقائياً بسبب
--reload). - جرب الروابط التالية في المتصفح:
http://127.0.0.1:8000/tasks– ستعيد جميع المهام.http://127.0.0.1:8000/tasks?completed=true– ستعيد المهام المكتملة فقط.http://127.0.0.1:8000/tasks?keyword=كتاب– ستعيد المهام التي تحتوي على كلمة "كتاب".http://127.0.0.1:8000/tasks?completed=false&keyword=تعلم– ستعيد المهام غير المكتملة التي تحتوي على كلمة "تعلم".
?keyword=كتاب&completed=true وستحصل على نفس النتيجة. FastAPI يتعامل معها كمعاملات مسماة (named parameters).
الفرق بين Path Parameters و Query Parameters
من المهم فهم متى نستخدم كل نوع:
- Path Parameters: تستخدم لتحديد مورد محدد (مثل: مهمة معينة، مستخدم معين). هي إجبارية وتكون جزءاً لا يتجزأ من هيكل الـ API.
- Query Parameters: تستخدم للتصفية، الفرز، أو الصفحات (pagination). هي اختيارية بشكل عام وتضيف مرونة للـ endpoint.
أخطاء شائعة وكيفية تجنبها
- الخلط بين الأنواع: إذا توقعت أن
task_idهو رقم، فتأكد من تحديد النوعint. إذا أرسل المستخدم نصاً، سيعيد FastAPI خطأ 422 (Unprocessable Entity) بدلاً من خطأ 500 (Internal Server Error). - نسيان القيم الافتراضية: إذا كان المعامل اختيارياً (مثل query parameter)، يجب أن تعطيه قيمة افتراضية (
Noneأو قيمة أخرى). وإلا سيعتبره FastAPI إجبارياً. - تعارض المسارات: تأكد من أن مساراتك لا تتعارض. على سبيل المثال، إذا كان لديك
/tasks/{task_id}و/tasks/create، فقد يحدث ارتباك. من الأفضل استخدام هيكل واضح مثل/tasks/{task_id}للمهام الفردية و/tasksللقائمة.
تمرين صغير
الآن حان دورك لتطبيق ما تعلمته. قم بالتالي:
- أنشئ endpoint جديد في نفس ملف
main.pyعلى المسار/items/{item_id}. - يجب أن يستقبل هذا الـ endpoint معامل مسار
item_idمن نوعint. - أضف معامل استعلام اختياري اسمه
qمن نوعstrوقيمته الافتراضيةNone. - يجب أن تعيد الدالة قاموساً يحتوي على
item_idوإذا تم توفيرq، أضف مفتاحاً اسمهqueryيحمل قيمةq.
مثال: عند زيارة /items/10?q=test يجب أن تحصل على: {"item_id":10, "query":"test"}.
حاول كتابة الكود بنفسك قبل النظر إلى الحل أدناه.
الحل (اضغط للعرض)
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
result = {"item_id": item_id}
if q:
result["query"] = q
return result
بهذا نكون قد تعلمنا كيفية جعل API الخاص بنا ديناميكياً باستخدام Path Parameters و Query Parameters. في الدرس القادم، سنتعلم كيفية استخدام Pydantic لإنشاء نماذج بيانات أكثر تعقيداً وتحسين التحقق من صحة البيانات.
جاري تحميل التقييمات...