🏠 Домашнее задание
⚡ ДЗ в двух словах
Это урок-повторение. LMS-задания для Summary session 6 из источника — это задания блока DRF. Ниже их полный разбор.
Задание 1: Эндпоинт POST /tasks/ — создание задачи.
Задание 2: Эндпоинты GET /tasks/ и GET /tasks/<id>/.
Задание 3: GET /tasks/stats/ — агрегация: всего задач, по статусам, просроченные.
Это не отдельное LMS-задание. Урок 32 — итоговое повторение DRF-блока (Уроки 26–31). В источнике (Summary session 6) разобраны задания LMS из блока DRF. Ниже представлена их полная формулировка с пошаговым решением.
LMS-задания DRF-блока
Задание 1: Эндпоинт для создания задачи
Цель: Создайте эндпоинт для создания новой задачи. Задача должна создаваться с полями title, description, status и deadline.
Шаги:
- Определите сериализатор для модели
Task. - Создайте представление для создания задачи.
- Создайте маршрут для обращения к представлению.
Задание 2: Эндпоинты для получения задач
Цель: Создайте два эндпоинта:
- Получение списка всех задач (GET /tasks/)
- Получение конкретной задачи по её ID (GET /tasks/<pk>/)
Шаги:
- Создайте представления для получения списка и одной задачи.
- Создайте маршруты для обращения к представлениям.
Задание 3: Агрегирующий эндпоинт для статистики задач
Цель: Создайте эндпоинт GET /tasks/stats/, возвращающий статистику:
- Общее количество задач
- Количество задач по каждому статусу
- Количество просроченных задач
Подготовка окружения
# Создать и активировать виртуальное окружение
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux/macOS
# Установить зависимости
pip install django djangorestframework
# Создать проект
django-admin startproject task_project
cd task_project
python manage.py startapp tasks
# Добавить приложения в settings.py
# INSTALLED_APPS += ['rest_framework', 'tasks']
# Первые миграции
python manage.py migrate
python manage.py runserver
Пошаговое решение
Шаг 1: Модель Task
# tasks/models.py
from django.db import models
class Task(models.Model):
STATUS_CHOICES = [
('todo', 'To Do'),
('in_progress', 'In Progress'),
('done', 'Done'),
]
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='todo'
)
deadline = models.DateField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"[{self.status}] {self.title}"
class Meta:
ordering = ['-created_at']
python manage.py makemigrations
python manage.py migrate
Шаг 2: Сериализатор (Задание 1)
# tasks/serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
created_at = serializers.DateTimeField(read_only=True)
class Meta:
model = Task
fields = '__all__'
def validate_deadline(self, value):
from django.utils import timezone
if value and value < timezone.now().date():
raise serializers.ValidationError(
"Дедлайн не может быть в прошлом."
)
return value
Шаг 3: Представления (Задания 1, 2, 3)
# tasks/views.py
from django.db.models import Count, Q
from django.utils import timezone
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Task
from .serializers import TaskSerializer
# Задание 1 — создание; Задание 2 — список
@api_view(['GET', 'POST'])
def task_list_create(request):
if request.method == 'GET':
tasks = Task.objects.all()
serializer = TaskSerializer(tasks, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = TaskSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Задание 2 — одна задача по ID
@api_view(['GET'])
def task_detail(request, pk):
try:
task = Task.objects.get(pk=pk)
except Task.DoesNotExist:
return Response({'error': 'Task not found'}, status=status.HTTP_404_NOT_FOUND)
serializer = TaskSerializer(task)
return Response(serializer.data)
# Задание 3 — агрегация
@api_view(['GET'])
def task_stats(request):
today = timezone.now().date()
stats = Task.objects.aggregate(
total=Count('id'),
todo=Count('id', filter=Q(status='todo')),
in_progress=Count('id', filter=Q(status='in_progress')),
done=Count('id', filter=Q(status='done')),
overdue=Count(
'id',
filter=Q(deadline__lt=today) & ~Q(status='done')
),
)
return Response(stats)
Шаг 4: Маршруты
# tasks/urls.py
from django.urls import path
from .views import task_list_create, task_detail, task_stats
urlpatterns = [
path('tasks/', task_list_create, name='task-list-create'),
path('tasks/<int:pk>/', task_detail, name='task-detail'),
path('tasks/stats/', task_stats, name='task-stats'),
]
# task_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('tasks.urls')),
]
Проверка в VS Code / Postman
Тестирование в терминале
# Запустить сервер
python manage.py runserver
# Создать задачу (POST)
# В Postman: POST http://127.0.0.1:8000/api/tasks/
# Body -> raw -> JSON:
# {
# "title": "Написать тесты",
# "description": "Unit-тесты для Task API",
# "status": "todo",
# "deadline": "2025-12-31"
# }
# Получить все задачи (GET)
# http://127.0.0.1:8000/api/tasks/
# Получить одну задачу (GET)
# http://127.0.0.1:8000/api/tasks/1/
# Статистика (GET)
# http://127.0.0.1:8000/api/tasks/stats/
Ожидаемый ответ /api/tasks/stats/
{
"total": 5,
"todo": 2,
"in_progress": 1,
"done": 2,
"overdue": 0
}
Проверка в VS Code (F5 / launch.json)
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Django",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver", "0.0.0.0:8000"],
"django": true,
"justMyCode": true
}
]
}
Нажмите F5 — откроется отладчик Django. Ставьте точки останова в views.py и отслеживайте значения переменных.
Связь с теорией
- Теория: Сериализаторы — ModelSerializer, is_valid, validated_data
- Теория: Представления — @api_view, Response, статусы
- Теория: Агрегация ORM — Count с filter=Q(...)
- Примеры — полный Task API с аннотированными комментариями