العودة للدورة|ابنِ واجهة REST API إنتاجية: من الصفر حتى النشر مع FastAPI
معمل

تهيئة مشروع TaskFlow

30 دقيقة
متوسط
محاولات مجانية غير محدودة

التعليمات

في هذا المعمل، ستقوم بإعداد الأساس الكامل لواجهة TaskFlow البرمجية. بنهاية التمرين، سيكون لديك حزمة Docker Compose عاملة مع FastAPI وPostgreSQL 18 وRedis — جميعها متصلة ومتحقق منها عبر نقطة نهاية فحص الصحة.

الخطوة 1: إنشاء هيكل مجلدات المشروع

أنشئ هيكل المجلدات التالي لمشروع TaskFlow:

mkdir -p taskflow/app/{api/v1,models,schemas,core,tests}
cd taskflow

أنشئ ملفات __init__.py في كل مجلد حزمة Python:

touch app/__init__.py
touch app/api/__init__.py
touch app/api/v1/__init__.py
touch app/models/__init__.py
touch app/schemas/__init__.py
touch app/core/__init__.py
touch app/tests/__init__.py

الخطوة 2: إنشاء ملف المتطلبات

أنشئ requirements.txt مع قيود الإصدارات:

# إطار العمل الويب
fastapi>=0.136,<1.0
uvicorn[standard]>=0.34,<1.0

# قاعدة البيانات
sqlalchemy>=2.0.49,<2.1
psycopg2-binary>=2.9.10,<3.0
alembic>=1.18.4,<2.0

# التحقق والإعدادات
pydantic>=2.13,<3.0
pydantic-settings>=2.8,<3.0

# المصادقة
PyJWT>=2.10,<3.0
pwdlib[argon2]>=0.2,<1.0

# التخزين المؤقت
redis>=7.1.1,<9.0

# الاختبار
pytest>=9.0.2,<10.0
anyio>=4.0,<5.0
httpx>=0.28,<1.0

# الأدوات المساعدة
python-dotenv>=1.0.1,<2.0
python-multipart>=0.0.20,<1.0

أمران في هذا الملف أهم من الملف نفسه.

1. شغّل المُحلّل قبل أن تثق به. كل سطر أعلاه يسمّي حزمة حقيقية ومُصانة — وهذا ليس كافياً. مجموعة القيود قد تصبح غير قابلة للتحقيق مع الوقت دون أن يكون أي سطر فيها خاطئاً: حزمة ترفع الحد الأدنى الذي تدعمه من حزمة أخرى، فيصبح السقف الذي كان صحيحاً يوم كُتب أدنى من الأرضية. يُبلغ pip عن هذا بالرسالة ResolutionImpossible، ولن يلتقطه أي شيء آخر. افحص الملف وحده قبل أن تبني عليه أي شيء:

pip install --dry-run -r requirements.txt

ضع الأمر نفسه في CI. هو أرخص حارس ستضيفه على الإطلاق.

2. النطاقات ليست ملف قفل (lockfile). القيود أعلاه تحدد الإصدارات المسموح بها، لا الإصدار الذي حصلت عليه فعلاً. شخصان يشغّلان pip install بفارق شهر سيحصلان على بناءين مختلفين من هذا الملف، وهذا نقيض قابلية التكرار. النطاقات مكانها requirements.txt، أما المجموعة المُحلّلة بدقة فمكانها ملف قفل تحفظه في المستودع — يُنتَج بـ pip freeze أو pip-compile أو uv lock. انشر من القفل، وطوّر على النطاق.

لاحظ أن تبعية الاختبار هنا هي anyio وليست pytest-asyncio. الاختبارات التي ستكتبها في المرحلة الرابعة تستخدم الواسم @pytest.mark.anyio، وهو من إضافة pytest التابعة لـ AnyIO نفسها. وتثبيت إضافة async ثانية لا يستخدمها أحد هو تحديداً ما يصنع مشكلة السقف المذكورة أعلاه.

الخطوة 3: إنشاء إعدادات البيئة

أنشئ ملف .env في جذر المشروع:

# التطبيق
APP_NAME=TaskFlow
APP_VERSION=0.1.0
DEBUG=true

# قاعدة البيانات
POSTGRES_USER=taskflow
POSTGRES_PASSWORD=taskflow_secret_2026
POSTGRES_DB=taskflow
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
DATABASE_URL=postgresql://taskflow:taskflow_secret_2026@postgres:5432/taskflow

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_URL=redis://redis:6379/0

# JWT (أنشئ مفتاحك السري الخاص في بيئة الإنتاج!)
JWT_SECRET_KEY=dev-secret-key-change-in-production
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30

الخطوة 4: إنشاء وحدة الإعدادات

أنشئ app/core/config.py:

from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    app_name: str = "TaskFlow"
    app_version: str = "0.1.0"
    debug: bool = False

    # قاعدة البيانات
    database_url: str = "postgresql://taskflow:taskflow_secret_2026@postgres:5432/taskflow"

    # Redis
    redis_url: str = "redis://redis:6379/0"

    # JWT
    jwt_secret_key: str = "dev-secret-key-change-in-production"
    jwt_algorithm: str = "HS256"
    jwt_access_token_expire_minutes: int = 30

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"


settings = Settings()

الخطوة 5: إنشاء تطبيق FastAPI

أنشئ app/main.py:

from fastapi import FastAPI
from app.core.config import settings

app = FastAPI(
    title=settings.app_name,
    version=settings.app_version,
    docs_url="/docs",
    redoc_url="/redoc",
)


@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "app": settings.app_name,
        "version": settings.app_version,
    }

الخطوة 6: إنشاء ملف Dockerfile

أنشئ Dockerfile مع بناء متعدد المراحل:

# ---- المرحلة 1: البناء ----
FROM python:3.13-slim AS builder

WORKDIR /build

COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# ---- المرحلة 2: التشغيل ----
FROM python:3.13-slim AS runtime

WORKDIR /app

# نسخ الحزم المثبتة من مرحلة البناء
COPY --from=builder /install /usr/local

# نسخ كود التطبيق
COPY . .

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

الخطوة 7: إنشاء إعدادات Docker Compose

أنشئ docker-compose.yml:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    env_file:
      - .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped

  postgres:
    image: postgres:18
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-taskflow}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-taskflow_secret_2026}
      POSTGRES_DB: ${POSTGRES_DB:-taskflow}
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U taskflow -d taskflow"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  redis:
    image: redis:8-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

الخطوة 8: البناء والتشغيل

شغّل الحزمة الكاملة:

docker compose up --build -d

تحقق من نقطة نهاية فحص الصحة:

curl http://localhost:8000/health

يجب أن ترى:

{
  "status": "healthy",
  "app": "TaskFlow",
  "version": "0.1.0"
}

تحقق من توثيق الواجهة البرمجية المُنشأ تلقائيا بزيارة http://localhost:8000/docs في متصفحك.

الخطوة 9: التحقق من جميع الخدمات

تحقق أن جميع الحاويات تعمل:

docker compose ps

يجب أن تظهر جميع الخدمات الثلاث (app، postgres، redis) بحالة Up (healthy).

ماذا تقدّم

المحرر يحتوي مسبقاً على 6 أقسام ملفات مع تعليقات TODO. استبدل كل TODO بالكود الفعلي. سيقوم المقيّم الذكي بتقييم كل قسم وفقاً لمعايير التقييم.

معايير التقييم

هيكل المشروع صحيح مع جميع المجلدات المطلوبة (app/api/v1, app/models, app/schemas, app/core, app/tests) وملفات __init__.py15 نقاط
requirements.txt يتضمن جميع الحزم المطلوبة (FastAPI, SQLAlchemy, Alembic, Pydantic, Redis, pytest, uvicorn) مع نطاقات إصدارات مثبتة بشكل صحيح15 نقاط
تطبيق FastAPI (app/main.py) مُعد بشكل صحيح مع نقطة نهاية /health عاملة تعيد JSON بالحالة واسم التطبيق والإصدار. وحدة الإعدادات (app/core/config.py) تستخدم pydantic-settings للتحميل من .env25 نقاط
Dockerfile يستخدم بناء متعدد المراحل (مرحلة البناء + مرحلة التشغيل)، يبدأ من python:3.13-slim، ينسخ فقط الحزم المثبتة إلى مرحلة التشغيل، ويكشف المنفذ 800020 نقاط
docker-compose.yml يعرّف ثلاث خدمات (app, postgres بصورة postgres:18, redis بصورة redis:8-alpine) مع فحوصات صحية، ومجلدات مسماة لاستمرارية البيانات، وdepends_on مع شروط صحية، وإعدادات متغيرات بيئة صحيحة25 نقاط

قائمة التحقق

0/6

حلك

محاولات مجانية غير محدودة