180 lines
9.6 KiB
Markdown
180 lines
9.6 KiB
Markdown
# 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://<host>/api/schema/ # باید 200 برگردونه (OpenAPI schema)
|
||
curl -i https://<host>/api/docs/ # باید 200 برگردونه (Swagger UI)
|
||
curl -i -X POST https://<host>/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` برمیگردونه.
|