---
alwaysApply: true
---

## 2. Django App (Module) Naming

| Item   | Convention | Example                    |
|--------|------------|----------------------------|
| App name | snake_case, **بدون** پسوند `_api` | `account`, `auth`, `sensor_hub` |

- نام اپ‌ها را با `_api` تمام **نکنید**. مثلاً به‌جای `account_api` از `account` استفاده کنید.
- برای ماژول‌های فقط API، همان نام دامنه کافی است (مثلاً `auth`، `account`).

---

## 3. Model and Database Field Naming

| Item              | Convention              | Example                                      |
|-------------------|-------------------------|----------------------------------------------|
| Model             | PascalCase              | `UserProfile`                                |
| Fields            | snake_case              | `first_name`, `email_address`                |
| Boolean           | `is_` / `has_` + name   | `is_active`, `has_paid`                      |
| Date/Time         | `created_at` / `updated_at` | `created_at`, `updated_at`               |
| ForeignKey / M2M  | snake_case, often model name | `author = ForeignKey(UserProfile)`     |
| Choices / Enum    | UPPER_SNAKE_CASE values | `role = CharField(choices=(("ADMIN","Admin"), ("USER","User")))` |

---

## 4. DRF Conventions

- **Serializer:** Validation + data transformation. Use PascalCase names.
- **Service layer:** All business logic lives here.
- **View:** Orchestration only — call services and return responses. No business logic in views.
- **URLs:** Define endpoints only. Use kebab-case for URL paths.

---

## 5. API Response Format

همه پاسخ‌های API باید فیلد `code` را برگردانند؛ مقدار آن برابر **HTTP status code** درخواست است (مثلاً 200، 201، 400، 404).

| فیلد  | توضیح                                  |
|-------|----------------------------------------|
| `code` | کد وضعیت HTTP (مثلاً 200، 404، 500)   |
| `msg`  | پیام (مثلاً "success" برای 2xx)       |
| `data` | دادهٔ برگشتی (اختیاری)                |

مثال:
```json
{"code": 200, "msg": "success", "data": {...}}
```

---

## 6. Simple Example: How the Layers Connect (users app)

```python
# models.py
class UserProfile(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email_address = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


# serializers.py
class UserCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = ["first_name", "last_name", "email_address"]


# services.py
def create_user(first_name, last_name, email_address):
    return UserProfile.objects.create(
        first_name=first_name,
        last_name=last_name,
        email_address=email_address,
    )


# views.py
class UserCreateAPIView(APIView):
    def post(self, request):
        serializer = UserCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = create_user(**serializer.validated_data)
        return Response({"code": 201, "msg": "success", "data": {"id": user.id}}, status=201)
```

- All names follow the conventions above.
- Business logic is in `services.py`.
- Serializer only validates and serializes.
- View only orchestrates (calls service, returns response).
