Keep a single README and remove extra markdown docs
EOF Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
584
API_DOCS_FA.md
584
API_DOCS_FA.md
@@ -1,584 +0,0 @@
|
||||
<div dir="rtl" lang="fa">
|
||||
|
||||
# مستندات API (Zoneco ORG)
|
||||
|
||||
این سند نحوهٔ کارکرد APIهای بکاند پروژه Zoneco ORG را به زبان فارسی توضیح میدهد.
|
||||
|
||||
---
|
||||
|
||||
## وضعیت تستها
|
||||
|
||||
```
|
||||
Ran 31 tests — OK (0 failures)
|
||||
```
|
||||
|
||||
| تعداد تست | گروه |
|
||||
|-----------|------|
|
||||
| ۷ تست | Admin Login |
|
||||
| ۶ تست | Contact Us |
|
||||
| ۱۱ تست | Compositions |
|
||||
| ۷ تست | Campaigns |
|
||||
|
||||
اجرای تستها:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python manage.py test api -v 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## اطلاعات پایه
|
||||
|
||||
| مقدار | مورد |
|
||||
|--------|------|
|
||||
| `{{base_url}}` | آدرس پایه |
|
||||
| `/api/` | پیشوند API |
|
||||
| JSON | فرمت پاسخ |
|
||||
| ۲۰ آیتم در هر صفحه | صفحهبندی |
|
||||
| `/admin/` | پنل ادمین |
|
||||
|
||||
### متغیر Postman
|
||||
|
||||
در فایل Postman از متغیر `{{base_url}}` استفاده شده است.
|
||||
مقدار آن را مطابق محیط اجرا (لوکال، سرور تست یا پروداکشن) تنظیم کنید.
|
||||
|
||||
**نمونهٔ آدرس کامل یک endpoint:**
|
||||
|
||||
```
|
||||
{{base_url}}/api/contact-us/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## سطح دسترسی
|
||||
|
||||
| دسترسی | عملیات |
|
||||
|--------|--------|
|
||||
| عمومی — بدون نیاز به ورود | لیست و جزئیات (متد `GET`) |
|
||||
| عمومی — بدون نیاز به ورود | ایجاد (متد `POST`) |
|
||||
| فقط ادمین — نیاز به توکن | ویرایش و حذف (متدهای `PUT`، `PATCH`، `DELETE`) |
|
||||
|
||||
---
|
||||
|
||||
## ۰. ورود ادمین (Admin Login)
|
||||
|
||||
| مقدار | مورد |
|
||||
|--------|------|
|
||||
| `{{admin_username}}` از env (`ADMIN_USERNAME`) | نام کاربری |
|
||||
| `{{admin_password}}` از env (`ADMIN_PASSWORD`) | رمز عبور |
|
||||
| `{{base_url}}/admin/` | پنل جنگو ادمین |
|
||||
| `POST {{base_url}}/api/admin/login/` | ورود از طریق API |
|
||||
|
||||
> نام کاربری و رمز در کد هاردکد نمیشوند. روی سرور در فایل `.env` تنظیم کنید.
|
||||
|
||||
### ورود و دریافت توکن
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/admin/login/
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "{{admin_username}}",
|
||||
"password": "{{admin_password}}"
|
||||
}
|
||||
```
|
||||
|
||||
**پاسخ نمونه:**
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "<token>",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "<admin_username>",
|
||||
"is_staff": true,
|
||||
"is_superuser": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
در درخواستهای محافظتشده این هدر را بفرستید:
|
||||
|
||||
```
|
||||
Authorization: Token <token>
|
||||
```
|
||||
|
||||
### اطلاعات ادمین فعلی
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/admin/me/
|
||||
Authorization: Token <token>
|
||||
```
|
||||
|
||||
### خروج (حذف توکن)
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/admin/logout/
|
||||
Authorization: Token <token>
|
||||
```
|
||||
|
||||
برای درخواستهای ادمین در Postman، ابتدا login کنید، سپس توکن را در متغیر `admin_token` بگذارید.
|
||||
|
||||
---
|
||||
|
||||
## ۱. تماس با ما (Contact Us)
|
||||
|
||||
**مسیر پایه:**
|
||||
|
||||
```
|
||||
/api/contact-us/
|
||||
```
|
||||
|
||||
### فیلدها
|
||||
|
||||
| توضیح | الزامی | نوع | فیلد |
|
||||
|-------|--------|-----|------|
|
||||
| نام و نام خانوادگی | بله | string | `name` |
|
||||
| ایمیل یا شماره تماس | بله | string | `email_or_phone` |
|
||||
| متن پیام | بله | string | `description` |
|
||||
| دستهبندی | بله | string | `category` |
|
||||
|
||||
**مقادیر مجاز برای `category`:**
|
||||
|
||||
- همکاری
|
||||
- فروش
|
||||
- پشتیبانی
|
||||
- درخواست مشاور
|
||||
- سایر
|
||||
|
||||
---
|
||||
|
||||
### دریافت لیست تماسها
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/contact-us/
|
||||
```
|
||||
|
||||
**پاسخ نمونه:**
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "احمد محمدی",
|
||||
"email_or_phone": "ahmad@example.com",
|
||||
"description": "سلام، سوالی دارم.",
|
||||
"category": "پشتیبانی",
|
||||
"created_at": "2025-12-17T12:00:00Z",
|
||||
"updated_at": "2025-12-17T12:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### دریافت یک تماس
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/contact-us/{id}/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ثبت تماس جدید
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/contact-us/
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**بدنه درخواست:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "احمد محمدی",
|
||||
"email_or_phone": "09121234567",
|
||||
"description": "میخواهم در مورد محصولات اطلاعات بگیرم.",
|
||||
"category": "فروش"
|
||||
}
|
||||
```
|
||||
|
||||
**کد پاسخ:** `201 Created`
|
||||
|
||||
---
|
||||
|
||||
### فیلتر بر اساس دستهبندی
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/contact-us/by_category/?category=پشتیبانی
|
||||
```
|
||||
|
||||
| توضیح | الزامی | پارامتر |
|
||||
|-------|--------|---------|
|
||||
| یکی از دستههای مجاز | بله | `category` |
|
||||
|
||||
اگر پارامتر `category` ارسال نشود، خطای `400` برمیگردد.
|
||||
|
||||
---
|
||||
|
||||
### ویرایش و حذف (ادمین)
|
||||
|
||||
```
|
||||
PUT {{base_url}}/api/contact-us/{id}/
|
||||
PATCH {{base_url}}/api/contact-us/{id}/
|
||||
DELETE {{base_url}}/api/contact-us/{id}/
|
||||
```
|
||||
|
||||
نیاز به احراز هویت ادمین دارد.
|
||||
|
||||
---
|
||||
|
||||
## ۲. ترکیبات (Compositions)
|
||||
|
||||
**مسیر پایه:**
|
||||
|
||||
```
|
||||
/api/compositions/
|
||||
```
|
||||
|
||||
هر ترکیب میتواند **چند تصویر** داشته باشد.
|
||||
یکی از تصاویر با فیلد `is_main: true` بهعنوان **تصویر اصلی** مشخص میشود.
|
||||
|
||||
### فیلدها
|
||||
|
||||
| توضیح | الزامی | نوع | فیلد |
|
||||
|-------|--------|-----|------|
|
||||
| نام ترکیب | بله | string | `name` |
|
||||
| توضیحات | بله | string | `description` |
|
||||
| یک یا چند فایل تصویر (فقط در ایجاد/ویرایش) | خیر | file[] | `uploaded_images` |
|
||||
| ایندکس تصویر اصلی (شمارش از ۰) | خیر | integer | `main_image_index` |
|
||||
|
||||
### محدودیت تصاویر
|
||||
|
||||
- فرمتهای مجاز: JPEG، PNG، WebP، GIF
|
||||
- حداکثر حجم هر فایل: **۵ مگابایت**
|
||||
- مسیر ذخیره: `media/compositions/`
|
||||
|
||||
---
|
||||
|
||||
### دریافت لیست ترکیبات
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/compositions/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### دریافت یک ترکیب
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/compositions/{id}/
|
||||
```
|
||||
|
||||
**پاسخ نمونه:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "ترکیب A",
|
||||
"description": "توضیحات ترکیب",
|
||||
"image": null,
|
||||
"image_url": null,
|
||||
"images": [
|
||||
{
|
||||
"id": 2,
|
||||
"image": "/media/compositions/img2.jpg",
|
||||
"image_url": "{{base_url}}/media/compositions/img2.jpg",
|
||||
"is_main": true,
|
||||
"created_at": "2025-12-17T12:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"image": "/media/compositions/img1.jpg",
|
||||
"image_url": "{{base_url}}/media/compositions/img1.jpg",
|
||||
"is_main": false,
|
||||
"created_at": "2025-12-17T11:00:00Z"
|
||||
}
|
||||
],
|
||||
"main_image": {
|
||||
"id": 2,
|
||||
"image_url": "{{base_url}}/media/compositions/img2.jpg",
|
||||
"is_main": true,
|
||||
"created_at": "2025-12-17T12:00:00Z"
|
||||
},
|
||||
"created_at": "2025-12-17T10:00:00Z",
|
||||
"updated_at": "2025-12-17T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### فیلتر بر اساس تاریخ ایجاد
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/compositions/by-created-at/?from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z
|
||||
```
|
||||
|
||||
| توضیح | الزامی | پارامتر |
|
||||
|-------|--------|---------|
|
||||
| برگشت ترکیبهایی که `created_at >= from` | حداقل یکی | `from` |
|
||||
| برگشت ترکیبهایی که `created_at <= to` | حداقل یکی | `to` |
|
||||
|
||||
فرمت تاریخ: ISO 8601 — مثال: `2026-06-01T00:00:00Z`
|
||||
|
||||
اگر هیچ پارامتری ارسال نشود، خطای `400` برمیگردد.
|
||||
|
||||
---
|
||||
|
||||
### ایجاد ترکیب (بدون تصویر)
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/compositions/
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "ترکیب تست",
|
||||
"description": "توضیحات ترکیب"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ایجاد ترکیب با چند تصویر
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/compositions/
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| مقدار نمونه | نوع | فیلد |
|
||||
|-------------|-----|------|
|
||||
| ترکیب A | text | `name` |
|
||||
| توضیحات | text | `description` |
|
||||
| image1.jpg | file | `uploaded_images` |
|
||||
| image2.jpg | file | `uploaded_images` |
|
||||
| 1 | text | `main_image_index` |
|
||||
|
||||
**نکته:** فیلد `uploaded_images` را برای هر تصویر یکبار تکرار کنید.
|
||||
|
||||
**نکته:** اگر `main_image_index` ارسال نشود، **اولین تصویر** بهعنوان تصویر اصلی انتخاب میشود.
|
||||
|
||||
---
|
||||
|
||||
### افزودن تصویر به ترکیب موجود (ادمین)
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/compositions/{id}/add-images/
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| نوع | فیلد |
|
||||
|-----|------|
|
||||
| file (یک یا چند فایل) | `uploaded_images` |
|
||||
| text (اختیاری) | `main_image_index` |
|
||||
|
||||
---
|
||||
|
||||
### تنظیم تصویر اصلی (ادمین)
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/compositions/{id}/set-main-image/
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"image_id": 3
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### حذف یک تصویر (ادمین)
|
||||
|
||||
```
|
||||
DELETE {{base_url}}/api/compositions/{id}/images/{image_id}/
|
||||
```
|
||||
|
||||
**کد پاسخ:** `204 No Content`
|
||||
|
||||
---
|
||||
|
||||
### ویرایش و حذف ترکیب (ادمین)
|
||||
|
||||
```
|
||||
PUT {{base_url}}/api/compositions/{id}/
|
||||
PATCH {{base_url}}/api/compositions/{id}/
|
||||
DELETE {{base_url}}/api/compositions/{id}/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۳. کمپینها (Campaigns)
|
||||
|
||||
**مسیر پایه:**
|
||||
|
||||
```
|
||||
/api/campaigns/
|
||||
```
|
||||
|
||||
### فیلدها
|
||||
|
||||
| توضیح | الزامی | نوع | فیلد |
|
||||
|-------|--------|-----|------|
|
||||
| نام کمپین | بله | string | `name` |
|
||||
| توضیحات | بله | string | `description` |
|
||||
| زمان شروع (ISO 8601) | بله | datetime | `start_time` |
|
||||
| زمان پایان (باید بعد از `start_time` باشد) | بله | datetime | `end_time` |
|
||||
| تصویر کمپین | خیر | file | `image` |
|
||||
|
||||
### فیلدهای محاسباتی (فقط خواندنی)
|
||||
|
||||
| توضیح | فیلد |
|
||||
|-------|------|
|
||||
| آیا کمپین الان فعال است | `is_active` |
|
||||
| آیا کمپین هنوز شروع نشده | `is_upcoming` |
|
||||
| آیا کمپین تمام شده | `is_ended` |
|
||||
|
||||
---
|
||||
|
||||
### دریافت لیست کمپینها
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/campaigns/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### دریافت یک کمپین
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/campaigns/{id}/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ایجاد کمپین
|
||||
|
||||
```
|
||||
POST {{base_url}}/api/campaigns/
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "کمپین نوروز",
|
||||
"description": "تخفیف ویژه نوروز",
|
||||
"start_time": "2026-03-01T00:00:00Z",
|
||||
"end_time": "2026-03-31T23:59:59Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### کمپینهای فعال
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/campaigns/active/
|
||||
```
|
||||
|
||||
کمپینهایی که زمان فعلی بین `start_time` و `end_time` قرار دارد.
|
||||
|
||||
---
|
||||
|
||||
### کمپینهای آینده
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/campaigns/upcoming/
|
||||
```
|
||||
|
||||
کمپینهایی که هنوز شروع نشدهاند.
|
||||
|
||||
---
|
||||
|
||||
### کمپینهای پایانیافته
|
||||
|
||||
```
|
||||
GET {{base_url}}/api/campaigns/ended/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ویرایش و حذف (ادمین)
|
||||
|
||||
```
|
||||
PUT {{base_url}}/api/campaigns/{id}/
|
||||
PATCH {{base_url}}/api/campaigns/{id}/
|
||||
DELETE {{base_url}}/api/campaigns/{id}/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## کدهای وضعیت HTTP
|
||||
|
||||
| معنی | کد |
|
||||
|------|-----|
|
||||
| موفق | `200` |
|
||||
| ایجاد شد | `201` |
|
||||
| حذف شد (بدون بدنه) | `204` |
|
||||
| داده نامعتبر | `400` |
|
||||
| دسترسی ندارید | `403` |
|
||||
| یافت نشد | `404` |
|
||||
|
||||
---
|
||||
|
||||
## فایل Postman
|
||||
|
||||
مجموعه Postman در مسیر زیر قرار دارد:
|
||||
|
||||
```
|
||||
backend/Zoneco_ORG_API.postman_collection.json
|
||||
```
|
||||
|
||||
### نحوه import
|
||||
|
||||
1. Postman را باز کنید
|
||||
2. گزینه **Import** را بزنید
|
||||
3. فایل `Zoneco_ORG_API.postman_collection.json` را انتخاب کنید
|
||||
4. متغیر `{{base_url}}` را مطابق محیط خود تنظیم کنید
|
||||
5. برای درخواستهای ادمین، در تب **Authorization** گزینه **Basic Auth** را فعال کنید
|
||||
|
||||
---
|
||||
|
||||
## خلاصه endpointها
|
||||
|
||||
| دسترسی | Endpoint | Method | # |
|
||||
|--------|----------|--------|---|
|
||||
| عمومی | `/api/admin/login/` | POST | 1 |
|
||||
| ادمین | `/api/admin/logout/` | POST | 2 |
|
||||
| ادمین | `/api/admin/me/` | GET | 3 |
|
||||
| عمومی | `/api/contact-us/` | GET | 4 |
|
||||
| عمومی | `/api/contact-us/` | POST | 5 |
|
||||
| عمومی | `/api/contact-us/{id}/` | GET | 6 |
|
||||
| عمومی | `/api/contact-us/by_category/?category=...` | GET | 7 |
|
||||
| ادمین | `/api/contact-us/{id}/` | PUT/PATCH/DELETE | 8 |
|
||||
| عمومی | `/api/compositions/` | GET | 9 |
|
||||
| عمومی | `/api/compositions/` | POST | 10 |
|
||||
| عمومی | `/api/compositions/{id}/` | GET | 11 |
|
||||
| عمومی | `/api/compositions/by-created-at/?from=...&to=...` | GET | 12 |
|
||||
| ادمین | `/api/compositions/{id}/add-images/` | POST | 13 |
|
||||
| ادمین | `/api/compositions/{id}/set-main-image/` | POST | 14 |
|
||||
| ادمین | `/api/compositions/{id}/images/{image_id}/` | DELETE | 15 |
|
||||
| ادمین | `/api/compositions/{id}/` | PUT/PATCH/DELETE | 16 |
|
||||
| عمومی | `/api/campaigns/` | GET | 17 |
|
||||
| عمومی | `/api/campaigns/` | POST | 18 |
|
||||
| عمومی | `/api/campaigns/{id}/` | GET | 19 |
|
||||
| عمومی | `/api/campaigns/active/` | GET | 20 |
|
||||
| عمومی | `/api/campaigns/upcoming/` | GET | 21 |
|
||||
| عمومی | `/api/campaigns/ended/` | GET | 22 |
|
||||
| ادمین | `/api/campaigns/{id}/` | PUT/PATCH/DELETE | 23 |
|
||||
|
||||
> **توجه:** در Postman قبل از هر مسیر، مقدار `{{base_url}}` را قرار دهید.
|
||||
> مثال: `{{base_url}}/api/campaigns/active/`
|
||||
|
||||
</div>
|
||||
221
DOCKER_README.md
221
DOCKER_README.md
@@ -1,221 +0,0 @@
|
||||
# Docker Setup for Zoneco ORG Backend
|
||||
|
||||
This document provides instructions for running the Zoneco ORG backend using Docker and Docker Compose.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine 20.10 or higher
|
||||
- Docker Compose 2.0 or higher
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Navigate to the backend directory:**
|
||||
```bash
|
||||
cd backend
|
||||
```
|
||||
|
||||
2. **Create a `.env` file** (copy from the template below):
|
||||
```bash
|
||||
# Copy and modify as needed
|
||||
SECRET_KEY=your-secret-key-here-change-in-production
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS=localhost,127.0.0.1,YOUR_SERVER_IP
|
||||
POSTGRES_DB=Zoneco_ORG
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=change-me
|
||||
POSTGRES_HOST=db
|
||||
POSTGRES_PORT=5432
|
||||
DJANGO_PORT=8000
|
||||
ADMIN_USERNAME=your-admin-username
|
||||
ADMIN_PASSWORD=your-admin-password
|
||||
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,http://YOUR_SERVER_IP:9123
|
||||
```
|
||||
|
||||
3. **Build and start the containers:**
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
4. **The application will be available at:**
|
||||
- API: `http://localhost:8000/api/`
|
||||
- Admin: `http://localhost:8000/admin/`
|
||||
|
||||
## Docker Commands
|
||||
|
||||
### Start services
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
### Start services in detached mode
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Stop services
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### Stop services and remove volumes (⚠️ deletes database data)
|
||||
```bash
|
||||
docker-compose down -v
|
||||
```
|
||||
|
||||
### View logs
|
||||
```bash
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### View logs for specific service
|
||||
```bash
|
||||
docker-compose logs -f web
|
||||
docker-compose logs -f db
|
||||
```
|
||||
|
||||
### Rebuild containers
|
||||
```bash
|
||||
docker-compose build --no-cache
|
||||
```
|
||||
|
||||
### Execute commands in running container
|
||||
```bash
|
||||
# Django shell
|
||||
docker-compose exec web python manage.py shell
|
||||
|
||||
# Create superuser
|
||||
docker-compose exec web python manage.py createsuperuser
|
||||
|
||||
# Run migrations manually
|
||||
docker-compose exec web python manage.py migrate
|
||||
|
||||
# Collect static files
|
||||
docker-compose exec web python manage.py collectstatic --noinput
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The Docker setup consists of:
|
||||
|
||||
1. **Web Service** (`web`):
|
||||
- Django application running with Gunicorn
|
||||
- Multi-stage Dockerfile for optimized image size
|
||||
- Non-root user for security
|
||||
- Automatic migrations and static file collection on startup
|
||||
- Health checks enabled
|
||||
|
||||
2. **Database Service** (`db`):
|
||||
- PostgreSQL 15 Alpine (lightweight)
|
||||
- Persistent data volume
|
||||
- Health checks to ensure readiness
|
||||
|
||||
## Features
|
||||
|
||||
### Security Best Practices
|
||||
- ✅ Multi-stage build for smaller image size
|
||||
- ✅ Non-root user execution
|
||||
- ✅ Environment variable configuration
|
||||
- ✅ No hardcoded secrets
|
||||
- ✅ Health checks for both services
|
||||
|
||||
### Production Ready
|
||||
- ✅ Gunicorn WSGI server
|
||||
- ✅ Automatic database migrations
|
||||
- ✅ Static file collection
|
||||
- ✅ Database connection retry logic
|
||||
- ✅ Proper logging
|
||||
|
||||
### Development Friendly
|
||||
- ✅ Volume mounts for media and static files
|
||||
- ✅ Hot-reload capability (with proper setup)
|
||||
- ✅ Easy access to Django management commands
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SECRET_KEY` | Django secret key | (required in production) |
|
||||
| `DEBUG` | Enable debug mode | `False` |
|
||||
| `ALLOWED_HOSTS` | Comma-separated allowed hosts | `localhost,127.0.0.1` |
|
||||
| `POSTGRES_DB` | Database name | `Zoneco_ORG` |
|
||||
| `POSTGRES_USER` | Database user | `postgres` |
|
||||
| `POSTGRES_PASSWORD` | Database password | `postgres` |
|
||||
| `POSTGRES_HOST` | Database host | `db` |
|
||||
| `POSTGRES_PORT` | Database port | `5432` |
|
||||
| `DJANGO_PORT` | Django application port | `8000` |
|
||||
| `CORS_ALLOWED_ORIGINS` | Comma-separated CORS origins | (see .env.example) |
|
||||
|
||||
## Volumes
|
||||
|
||||
- `postgres_data`: Persistent PostgreSQL data
|
||||
- `./media`: Media files (images, uploads)
|
||||
- `./staticfiles`: Collected static files
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database connection errors
|
||||
```bash
|
||||
# Check if database is healthy
|
||||
docker-compose ps
|
||||
|
||||
# Check database logs
|
||||
docker-compose logs db
|
||||
|
||||
# Restart services
|
||||
docker-compose restart
|
||||
```
|
||||
|
||||
### Permission issues
|
||||
```bash
|
||||
# Fix media/staticfiles permissions
|
||||
sudo chown -R $USER:$USER media staticfiles
|
||||
```
|
||||
|
||||
### Port already in use
|
||||
```bash
|
||||
# Change port in .env file
|
||||
DJANGO_PORT=8001
|
||||
# Then update docker-compose.yml or restart
|
||||
```
|
||||
|
||||
### Clear everything and start fresh
|
||||
```bash
|
||||
docker-compose down -v
|
||||
docker-compose build --no-cache
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For production deployment:
|
||||
|
||||
1. **Set strong SECRET_KEY:**
|
||||
```bash
|
||||
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
|
||||
```
|
||||
|
||||
2. **Set DEBUG=False** in `.env`
|
||||
|
||||
3. **Configure proper ALLOWED_HOSTS**
|
||||
|
||||
4. **Use strong database passwords**
|
||||
|
||||
5. **Consider using:**
|
||||
- Reverse proxy (nginx)
|
||||
- SSL/TLS certificates
|
||||
- Separate database server
|
||||
- Backup strategy
|
||||
- Monitoring and logging
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
backend/
|
||||
├── Dockerfile # Multi-stage production Dockerfile
|
||||
├── docker-compose.yml # Service orchestration
|
||||
├── .dockerignore # Files to exclude from build
|
||||
├── entrypoint.sh # Startup script
|
||||
├── requirements.txt # Python dependencies
|
||||
└── DOCKER_README.md # This file
|
||||
```
|
||||
|
||||
10
README.md
10
README.md
@@ -299,15 +299,9 @@ DB constraint: only one `is_main=True` per composition.
|
||||
|
||||
## Postman Collection
|
||||
|
||||
Import `backend/Zoneco_ORG_API.postman_collection.json` into Postman.
|
||||
Import `Zoneco_ORG_API.postman_collection.json` into Postman.
|
||||
|
||||
Set the `base_url` collection variable to your server address.
|
||||
|
||||
---
|
||||
|
||||
## Persian Documentation
|
||||
|
||||
Full Persian API documentation: `backend/API_DOCS_FA.md`
|
||||
Set collection variables: `base_url`, `admin_username`, `admin_password`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user