الخطوة 2 في الواجهة الخلفية: مرحبًا Flask
ستنشئ الآن أول خادم ويب لك باستخدام Flask، وستفهم كيف تعمل المسارات.
ما الذي ستتعلمه
- تشغيل خادم Flask
- تعريف المسارات باستخدام
@app.route() - إرجاع JSON باستخدام
jsonify() - دورة الطلب والاستجابة
الخطوة 1: إنشاء تطبيق Flask الأساسي
عدّل backend/app/__init__.py:
from flask import Flask, jsonify
def create_app():
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Hello Flask!"})
return app
if __name__ == "__main__":
app = create_app()
app.run(debug=True, port=5000)
الخطوة 2: تشغيل الخادم
اختر الطريقة التي تناسب إعدادك من الخطوة 1:
الخيار أ — بيئة افتراضية:
cd aiproject/backend
source venv/bin/activate
python app/__init__.py
الخيار ب — Docker:
cd aiproject/backend
docker compose up
يجب أن ترى:
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000
الخطوة 3: اختباره
افتح طرفية جديدة وشغّل:
curl http://127.0.0.1:5000/
الناتج المتوقع:
{"message":"Hello Flask!"}
أو افتح http://127.0.0.1:5000/ في متصفحك.
الخطوة 4: إضافة مسار للحالة
لنضف نقطة نهاية لفحص الصحة. حدّث __init__.py:
from flask import Flask, jsonify
def create_app():
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Hello Flask!"})
@app.route("/api/status")
def status():
return jsonify({"status": "ok", "version": "1.0"})
return app
if __name__ == "__main__":
app = create_app()
app.run(debug=True, port=5000)
اختبره:
curl http://127.0.0.1:5000/api/status
# → {"status":"ok","version":"1.0"}
الخطوة 5: فهم المسارات
المسار هو نمط URL. عندما يصل طلب، يطابق Flask عنوان URL بالدالة الصحيحة:
@app.route("/") # GET / → يستدعي home()
@app.route("/api/status") # GET /api/status → يستدعي status()
ترجع الدالة بيانات، ويحوّلها jsonify() إلى JSON.
كيف يعمل Flask
- تشغّل الخادم باستخدام
app.run() - يستمع Flask إلى طلبات HTTP الواردة على المنفذ 5000
- عند وصول طلب، يطابق Flask عنوان URL بالمسار المناسب
- يستدعي Flask الدالة المطابقة
- ترجع الدالة استجابة (JSON)
- يرسل Flask الاستجابة مرة أخرى إلى العميل
الخطوة 6: فحص كودك (اكتشاف الأخطاء مبكرًا)
الآن شغّل ruff لفحص كودك بحثًا عن مشكلات:
cd aiproject/backend
ruff check app/
إذا كان كل شيء سليمًا فلن ترى أي ناتج. هذا جيد — فهو يعني عدم وجود مشكلات.
جرّب أن ترتكب خطأً عن قصد — أضف استيرادًا غير مستخدم، ثم شغّل ruff مرة أخرى:
import os # ← هذا السطر لا يُستخدم أبدًا
ruff check app/
# → app/__init__.py:1:1: F401 `os` imported but unused
اكتشف ruff الاستيراد غير المستخدم. أزله وشغّل ruff مرة أخرى — سيكون الفحص نظيفًا.
لماذا يهم هذا: يكتشف الفحص الأخطاء البرمجية قبل أن تشغّل الكود أصلًا. استيراد ناقص، أو خطأ مطبعي في اسم متغير، أو دالة غير مستخدمة — يجدها ruff كلها. المطورون المحترفون يشغّلون أدوات الفحص قبل كل commit.
الخطوة 7: كتابة أول اختبار آلي
حتى الآن كنت تختبر باستخدام curl — بكتابة الأوامر يدويًا. هذا يفي بالغرض، لكنه بطيء ويسهل نسيانه.
بدلًا من ذلك، اكتب اختبارًا آليًا يتحقق من الشيء نفسه:
أنشئ backend/tests/test_status.py:
def test_status_returns_ok(client):
response = client.get("/api/status")
assert response.status_code == 200
assert response.get_json() == {"status": "ok"}
هذا الاختبار:
1. يرسل طلب GET إلى /api/status
2. يتحقق من أن رمز الحالة 200 (نجاح)
3. يتحقق من أن جسم JSON هو {"status": "ok"}
شغّله:
cd aiproject/backend
pip install pytest
python -m pytest tests/ -v
الناتج المتوقع:
tests/test_status.py::test_status_returns_ok PASSED
نجح اختبار واحد. أصبح لديك الآن اختبار آلي يمكنك تشغيله في ثانية واحدة بدلًا من تنفيذ curl يدويًا.
الخطوة 8: التجربة
@app.route("/api/greet/<name>")
def greet(name):
return jsonify({"message": f"Hello, {name}!"})
اختبر: curl http://127.0.0.1:5000/api/greet/Alice
→ {"message":"Hello, Alice!"}
الشرح: لماذا jsonify()؟
يستطيع Flask إرجاع سلاسل نصية أو HTML مباشرة، لكن تطبيق الجوال لدينا يحتاج إلى JSON. تحوّل jsonify() قواميس Python إلى صيغة JSON وتضبط ترويسة Content-Type المناسبة.
بدون jsonify():
return {"message": "hello"} # في إصدارات Flask الأقدم، لم يكن هذا يعمل!
مع jsonify():
return jsonify({"message": "hello"}) # استجابة JSON صحيحة
التحقق
curl http://127.0.0.1:5000/
# → {"message":"Hello Flask!"}
curl http://127.0.0.1:5000/api/status
# → {"status":"ok","version":"1.0"}
إذا نجح كلا الأمرين، فأنت مستعد للخطوة 3.