📖 Теория: архитектура проекта Agile Projects
⚡ Ключевые концепции
- Модуль apps/ — все приложения вынесены в одну папку для чистоты архитектуры
- Модуль models/ — каждая модель в отдельном файле (
tag.py,project.py) - Enum choices — статусы и приоритеты через Python
Enum, а не строки - APIView — базовый класс DRF для ручного управления методами HTTP
- Agile git-flow — каждая задача = один коммит + pull request
Концепция проекта
«Agile Projects» — веб-платформа для управления проектами, задачами и сотрудниками. Платформа обеспечивает:
- Отслеживание статусов задач, их приоритетности и исполнителей
- Лёгкое добавление файлов к проектам
- Аналитику: количество задач, скорость закрытия, нагруженность проекта
Технологический стек: Django 5.x + DRF 3.15+. Все взаимодействия через REST API.
Архитектура: модуль apps/
Для чистоты структуры все Django-приложения помещаются в папку apps/, которая является Python-пакетом (содержит __init__.py).
agile_projects/ ← корневой пакет Django
apps/
__init__.py
routers.py ← общий URL-маршрутизатор
tasks/ ← приложение задач и тегов
models/
__init__.py
tag.py
task.py
choices/
statuses.py
priority.py
serializers/
tag_serializers.py
views/
tag_views.py
utils/
set_end_of_month.py
urls.py
projects/ ← приложение проектов и файлов
models/
__init__.py
project.py
serializers/
project_serializers.py
project_file_serializers.py
views/
project_views.py
project_file_views.py
utils/
upload_file_helpers.py
urls.py
При регистрации в INSTALLED_APPS указывается полный путь через точку:
INSTALLED_APPS = [
...
'apps.tasks.apps.TasksConfig',
'apps.projects.apps.ProjectsConfig',
]
Модуль models/ вместо models.py
Вместо одного файла models.py создаётся пакет models/, где каждая модель живёт в отдельном файле. В models/__init__.py нужно явно экспортировать классы:
# apps/tasks/models/__init__.py
from apps.tasks.models.tag import Tag
from apps.tasks.models.task import Task
Enum choices для Django-полей
Вместо хардкода строк используют Python Enum-классы. Это обеспечивает автодополнение IDE, защиту от опечаток, единое место изменения значений.
# apps/tasks/choices/statuses.py
from enum import Enum
class Statuses(Enum):
NEW = "NEW"
IN_PROGRESS = "IN_PROGRESS"
PENDING = "PENDING"
BLOCKED = "BLOCKED"
TESTING = "TESTING"
CLOSED = "CLOSED"
@classmethod
def choices(cls):
return [(attr.name, attr.value) for attr in cls]
models.TextChoices и models.IntegerChoices. Они предпочтительнее кастомного Enum в продакшн-коде.Agile git-workflow в учебном проекте
Каждая задача практикума завершается циклом:
- Написать код
python manage.py makemigrations+python manage.py migrate- Запустить сервер, проверить работу
git add . && git commit -m "feat: описание" && git push origin <branch>- Открыть pull request для код-ревью
Это имитирует реальный рабочий процесс в Agile-команде с частыми небольшими коммитами.
APIView: ручное управление HTTP-методами
APIView — базовый класс DRF, аналог Django View, но с автоматической обработкой Content-Type, парсингом тела запроса и рендерингом ответа.
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework import status
class TagListAPIView(APIView):
def get(self, request: Request) -> Response:
...
def post(self, request: Request) -> Response:
...
Каждый HTTP-метод реализуется как метод класса с тем же именем в нижнем регистре.
Работа с файлами в DRF
Для загрузки файлов запрос должен иметь Content-Type: multipart/form-data. Файл доступен через request.FILES["key"], текстовые поля — через request.data["key"].
Хорошая практика — писать по частям (chunked write), чтобы не держать весь файл в памяти:
with open(file_path, 'wb') as f:
for chunk in file_content.chunks():
f.write(chunk)