# Tadrisino API بک‌اند اپلیکیشن آموزشی Tadrisino — Django + Django REST Framework. احراز هویت با OTP، محتوای درسی و پیشرفت کاربر، دستیار هوش مصنوعی، اشتراک و پرداخت، تخفیف، اعلان‌ها، همکاری در فروش، پشتیبانی و حساب خانواده. | اپ | مسئولیت | |---|---| | `accounts` | احراز هویت، session، پروفایل کاربر | | `content` | پایه‌ها، مباحث، درس‌ها، سوال‌ها، پیشرفت | | `progress` | آمار، لیدربرد، streak | | `ai_tutor` | مکالمات دستیار هوش مصنوعی | | `subscription` / `payment` / `discount` | پلن، سفارش، تراکنش، کد تخفیف | | `notifications`, `affiliate`, `support`, `family` | امکانات جانبی | | `statuslog` | لاگ عمومی تغییر status، مستقل از بقیه‌ی اپ‌ها | --- ## ۱. راه‌اندازی محیط توسعه ### پیش‌نیازها - پایتون ۳.۱۲ - pip ### تنظیم محیط ```bash python3 -m venv venv source venv/bin/activate # ویندوز: venv\Scripts\activate pip install -r requirements.txt cp .env.example .env ``` `.env.example` (تمام متغیرهایی که واقعاً توسط اپ خونده می‌شن): ```env DJANGO_DEBUG=1 DJANGO_SECRET_KEY= DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1 CACHE_URL= KAVENEGAR_API_KEY= GRAFANA_ADMIN_PASSWORD=admin ``` مقادیر `.env` رو به شل خودتون export کنید (یا از `direnv`/`python-dotenv` استفاده کنید): ```bash export DJANGO_DEBUG=1 # ویندوز (PowerShell): $env:DJANGO_DEBUG=1 ``` > `DEBUG` دیفالتش `False` است. برای فعال‌کردنِ کمک‌کننده‌های dev-only در Swagger > (`DEV_MASTER_OTP` و فیلدِ `devOtp` توی پاسخ‌ها)، محلی `DJANGO_DEBUG=1` رو ست کنید. ### سریع‌ترین راه اجرای پروژه ```bash python manage.py migrate python manage.py runserver ``` اپ روی `http://127.0.0.1:8000` بالا میاد. ### مایگریشن‌ها ```bash python manage.py migrate ``` ### دیتای تستی (Seed) یک دیتاست کوچک و idempotent می‌سازه که همه‌ی اپ‌ها رو پوشش می‌ده (کاربر، محتوا، پیشرفت، اشتراک، پرداخت، تخفیف، دستیار هوش مصنوعی، اعلان، افیلیت، پشتیبانی، خانواده). اجرای مکرر امن است — با `get_or_create` هیچ رکورد تکراری‌ای نمی‌سازه. پیش‌فرض فقط وقتی `DEBUG=True` اجرا می‌شه، مگر با `--force`. ```bash python manage.py seed_test_data # لوکال (DEBUG=True) python manage.py seed_test_data --force # staging (DEBUG=False) python manage.py seed_test_data --reset # پاک‌کردنِ دیتای قبلیِ seed و ساختِ دوباره ``` ### مستندات API | | | |---|---| | Swagger UI | `http://127.0.0.1:8000/api/docs/` | | Redoc | `http://127.0.0.1:8000/api/redoc/` | | OpenAPI schema | `http://127.0.0.1:8000/api/schema/` | | پنل ادمین | `http://127.0.0.1:8000/admin/` | **شروع سریع در Swagger:** 1. `POST /api/auth/session` با `{"type":"guest","deviceId":"d_test1"}` → یک `token` بگیرید. 2. روی دکمه‌ی **Authorize** بزنید و فقط خودِ `token` رو (بدون کلمه‌ی Bearer) وارد کنید. 3. برای تست لاگین با شماره: `POST /api/auth/otp/request` بزنید، یا در محیط توسعه کد **0000** رو با هر شماره‌ای در `POST /api/auth/login` امتحان کنید (dev-only، نیاز به `DEBUG=True`). ### دستورهای پرکاربرد ```bash python manage.py createsuperuser # اختیاری، برای /admin python manage.py test # اجرای کل تست‌سوییت ``` --- ## ۲. راهنمای دیپلوی پروداکشن ### متغیرهای محیطی موردنیاز | متغیر | لازم در پروداکشن | توضیح | |---|---|---| | `DJANGO_DEBUG` | باید ست‌نشده یا `0` باشه | دیفالت‌های امنیتیِ پروداکشن رو فعال می‌کنه | | `DJANGO_SECRET_KEY` | **بله** | بدونش وقتی `DEBUG=False` است اپ اصلاً بالا نمیاد | | `DJANGO_ALLOWED_HOSTS` | **بله** | لیستِ host ها، کاما-جدا | | `CACHE_URL` | **بله** | آدرسِ Redis، مثلاً `redis://host:6379/0` — برای rate limitِ مشترک وقتی `DEBUG=False` لازمه | | `KAVENEGAR_API_KEY` | **بله** | ارسال واقعیِ OTP از طریق کاوه‌نگار | | `GRAFANA_ADMIN_PASSWORD` | فقط اگه از استکِ Grafana استفاده می‌کنید | بخشِ Docker پایین رو ببینید | ### تنظیمات پروداکشن - `DEBUG` باید ست **نشه** (یا `0` باشه). با `DEBUG=False`: - `SECRET_KEY` اجباریه — هیچ fallback ناامنی وجود نداره. - `CACHE_URL` (Redis) اجباریه — `LocMemCache` فقط برای dev هست. - `DEV_MASTER_OTP` و فیلدِ `devOtp` توی پاسخ‌ها غیرفعال می‌شن. - برای ترافیک واقعی به‌جای SQLیت پیش‌فرض، از یک دیتابیسِ پروداکشن‌گرید استفاده کنید (پروژه با همون SQLite شیپ می‌شه؛ عوض‌کردنِ engine یک تصمیمِ زیرساختیه، خارج از این ریپو). - از طریق یک سرورِ WSGI/ASGI (مثلاً gunicorn) جلوی اپ سرو کنید — تنظیماتِ Docker موجود همچنان `runserver` اجرا می‌کنه و فقط برای dev/local مستند شده (پایین رو ببینید). ### تنظیمات Docker/دیپلوی `docker-compose.yml` موجود، اپ رو **به‌همراه** یک استکِ لاگِ متمرکز (Loki + Grafana Alloy + Grafana) اجرا می‌کنه. این یک تنظیمِ **dev/local** هست، نه دیپلویِ پروداکشن (سرویسِ `django` همچنان `runserver` اجرا می‌کنه، نه یک سرورِ پروداکشن). ```bash cp .env.example .env # اختیاری — بدونش compose از دیفالت‌های dev استفاده می‌کنه docker compose up --build ``` | سرویس | آدرس | توضیح | |---|---|---| | اپ Django | `http://localhost:8000` | | | Grafana | `http://localhost:3000` | دسترسیِ anonymous admin، فقط محیطِ محلی | | Loki | `http://localhost:3100` | ذخیره‌سازیِ لاگ، در معرضِ کاربر نیست | | Alloy | `http://localhost:12345` | رابطِ دیباگِ اختیاری | ### ترتیبِ لازمِ بالا آمدن Compose خودش این رو مدیریت می‌کنه: 1. اول `loki` بالا میاد. 2. `alloy` و `grafana` بعد از `loki` بالا میان (`depends_on`). 3. `django` هیچ وابستگی‌ای به استکِ لاگ نداره — خودش `migrate` بعد `runserver` رو اجرا می‌کنه و منتظرِ Loki/Alloy/Grafana نمی‌مونه. ### مایگریشن‌ها ```bash python manage.py migrate --noinput ``` در Docker، این به‌صورت خودکار به‌عنوان بخشی از دستورِ سرویسِ `django`، قبل از `runserver` اجرا می‌شه. ### راهنمای seed برای staging/تست - هرگز `seed_test_data` رو روی یک دیتابیسِ پروداکشنِ واقعی اجرا نکنید. - روی staging (`DEBUG=False`)، صریحاً با `--force` اجرا کنید: ```bash python manage.py seed_test_data --force ``` - برای پاک‌کردن و ساختِ دوباره‌ی دیتای seed بین چرخه‌های تست، از `--reset` استفاده کنید. همه‌ی رکوردهای seed‌شده در فیلدهای متنیِ قابل‌مشاهده با تگِ `[SEED]` مشخص شدن، برای شناساییِ راحت‌تر و پاک‌سازی. ### چطور API دیپلوی‌شده رو verify کنیم ```bash curl -i https:///api/schema/ # باید 200 برگردونه (OpenAPI schema) curl -i https:///api/docs/ # باید 200 برگردونه (Swagger UI) curl -i -X POST https:///api/auth/session \ -H "Content-Type: application/json" \ -d '{"type":"guest","deviceId":"verify-1"}' # باید یک token برگردونه ``` ### نکات مهمِ پروداکشن - `DEV_MASTER_OTP` (کد `0000`) و فیلدِ `devOtp` توی پاسخ‌ها فقط وقتی `DEBUG=True` وجود دارن — قبل از رفتن روی محیطِ واقعی مطمئن بشید `DEBUG` خاموشه. - احراز هویت با Bearer token امضاشده و stateless (`django.core.signing`)، هماهنگ با مدل `Session` — بدون کتابخانه‌ی JWT خارجی. - `accounts.User` یک مدل بیزنسیِ مستقله، **نه** `AUTH_USER_MODEL` جنگو. - همه‌ی لاگ‌های ساختاریافته‌ی درخواست (`method`/`path`/`status`/`duration`/`user`، بدونِ بدنه/هدر/سکرت) روی stdout و — وقتی `LOG_DIR` ست باشه (مثلِ داخلِ Docker) — در `/var/log/django/app.log` نوشته می‌شن؛ قابلِ مشاهده در Grafana از طریقِ استکِ بالا. - `POST /api/ai/ask` فعلاً پاسخ stub برمی‌گردونه؛ محلِ اتصالِ مدلِ واقعی `generate_tutor_answer` در `ai_tutor/views.py` است. - ارسالِ OTP از طریقِ کاوه‌نگار (`KAVENEGAR_API_KEY`) انجام می‌شه؛ شکستِ ارسال به‌جای موفقیتِ ساختگی، خطای صریحِ `503` برمی‌گردونه.