🏠 Практика: закрепление Agile Projects ч.2

К оглавлению урока

Примечание: Для урока 30 отдельного LMS-задания нет. Данный раздел содержит самостоятельное закрепляющее задание, построенное на расширении мини-проекта из занятия.

⚡ Задание кратко

Расширить проект «Agile Projects»: добавить поиск задач по статусу, сериализатор UserSerializer с отображением проекта, зарегистрировать эндпоинт /api/v1/users/. Проверить через Postman.

  • GET /api/v1/tasks/?status=in_progress — фильтр по статусу
  • GET /api/v1/users/ — список пользователей с email, проектом, позицией
  • POST /api/v1/users/ — создание пользователя

Задание: Расширение проекта Agile Projects

Цель

Применить навыки урока 30 на практике: расширить готовый мини-проект новой функциональностью.

Часть 1: Фильтрация задач по статусу

Добавить в TasksListAPIView.get_objects() фильтрацию по query-параметру status:

# GET /api/v1/tasks/?status=in_progress
# GET /api/v1/tasks/?project_name=MyProject&status=done

def get_objects(self) -> QuerySet:
    project_name = self.request.query_params.get('project_name')
    assignee_email = self.request.query_params.get('assignee_email')
    status_filter = self.request.query_params.get('status')   # НОВЫЙ ФИЛЬТР

    qs = Task.objects.all()
    if project_name:
        qs = qs.filter(project__name=project_name)
    if assignee_email:
        qs = qs.filter(assignee__email=assignee_email)
    if status_filter:
        qs = qs.filter(status=status_filter)
    return qs

Часть 2: API для пользователей

Создать сериализатор и view для модели User (задание 6 урока).

2.1 Создать UserListSerializer

# apps/users/serializers/user_serializers.py
from rest_framework import serializers
from apps.users.models import User
from apps.projects.serializers.project_serializers import ProjectShortInfoSerializer

class UserListSerializer(serializers.ModelSerializer):
    project = ProjectShortInfoSerializer(read_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'first_name', 'last_name', 'position', 'project')

2.2 Создать UserCreateSerializer

class UserCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'email', 'first_name', 'last_name', 'position', 'password')
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        password = validated_data.pop('password')
        user = User(**validated_data)
        user.set_password(password)   # хэширование пароля
        user.save()
        return user

2.3 Создать UserListAPIView

# apps/users/views/user_views.py
from rest_framework.generics import ListCreateAPIView

class UserListAPIView(ListCreateAPIView):
    def get_serializer_class(self):
        if self.request.method == 'GET':
            return UserListSerializer
        return UserCreateSerializer

    def get_queryset(self):
        return User.objects.filter(deleted=False).select_related('project')

2.4 Зарегистрировать URL

# apps/users/urls.py
from django.urls import path
from apps.users.views.user_views import UserListAPIView

urlpatterns = [
    path('', UserListAPIView.as_view()),
]

# config/urls.py — добавить:
path('api/v1/users/', include('apps.users.urls')),

Подготовка окружения

1. Установка зависимостей

python -m venv venv
venv\Scripts\activate          # Windows PowerShell

pip install django djangorestframework
pip install django-environ     # для .env файла

2. Запуск проекта

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser   # email вместо username
python manage.py runserver

Проверка в Postman

Проверочные запросы

Метод URL Ожидаемый результат
GET/api/v1/tasks/?status=in_progressСписок задач со статусом in_progress
GET/api/v1/tasks/?page=2Вторая страница (5 записей), поля count/next/previous
GET/api/v1/users/Список пользователей с вложенным project
POST/api/v1/users/Создание пользователя, 201 Created
POST/api/v1/projects/files/ (form-data)Загрузка файла, проверка валидации размера и расширения
DELETE/api/v1/projects/files/1/Удаление файла из БД и диска

Загрузка файла через Postman

  1. Метод: POST
  2. URL: http://127.0.0.1:8000/api/v1/projects/files/
  3. Body → form-data
  4. Добавить поля:
    • project_id = 1 (Type: Text)
    • file = выбрать файл (Type: File)

Проверка в VS Code

Терминал + F5

# .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Django",
            "type": "debugpy",
            "request": "launch",
            "program": "${workspaceFolder}/manage.py",
            "args": ["runserver"],
            "django": true
        }
    ]
}

После запуска через F5 открой http://127.0.0.1:8000/api/v1/ — DRF покажет browsable API.

Точки останова (breakpoints)

Поставь точку останова в методе validate_name сериализатора — VS Code остановится при POST-запросе и покажет значение value. Это удобно для отладки валидации.

Связь с теорией