🏠 Домашнее задание 10

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

⚡ Суть задания

Проект «Менеджер задач» — CRUD-операции с моделями Task и SubTask.

  • Создать Task «Prepare presentation» и 2 SubTask к ней
  • Прочитать: все Task со статусом «New»; SubTask со статусом «Done» с истёкшим сроком
  • Изменить: статус, срок и описание нескольких задач
  • Удалить: Task «Prepare presentation» со всеми подзадачами
  • Сдать: код + скриншоты консоли

Текст задания (из LMS)

Проект «Менеджер задач» — ORM запросы
Цель: Освоение основных операций CRUD (Create, Read, Update, Delete) на примере заданных моделей.

Выполните запросы:

1. Создание записей:

  • Task:
    • title: "Prepare presentation"
    • description: "Prepare materials and slides for the presentation"
    • status: "New"
    • deadline: Today's date + 3 days
  • SubTasks для "Prepare presentation":
    1. title: "Gather information", description: "Find necessary information for the presentation", status: "New", deadline: Today's date + 2 days
    2. title: "Create slides", description: "Create presentation slides", status: "New", deadline: Today's date + 1 day

2. Чтение записей:

  • Tasks со статусом "New": Вывести все задачи, у которых статус "New".
  • SubTasks с просроченным статусом "Done": Вывести все подзадачи, у которых статус "Done", но срок выполнения истёк.

3. Изменение записей:

  • Измените статус "Prepare presentation" на "In progress".
  • Измените срок выполнения для "Gather information" на два дня назад.
  • Измените описание для "Create slides" на "Create and format presentation slides".

4. Удаление записей:

  • Удалите задачу "Prepare presentation" и все её подзадачи.
Оформление ответа: Прикрепите все выполненные запросы (код) и скриншоты с консоли к ответу на домашнее задание.

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

1. Создание виртуального окружения

# В папке вашего Django-проекта
python -m venv venv

# Активация (Windows PowerShell)
.\venv\Scripts\Activate.ps1

# Активация (Linux/macOS)
source venv/bin/activate

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

pip install django
# Если используете requirements.txt:
pip install -r requirements.txt

3. Создание проекта и приложения (если нужно с нуля)

django-admin startproject task_manager .
python manage.py startapp tasks

4. Модели для ДЗ

Создайте файл tasks/models.py с моделями Task и SubTask:

from django.db import models


class Task(models.Model):
    STATUS_CHOICES = [
        ("New", "New"),
        ("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="New"
    )
    deadline = models.DateField(null=True, blank=True)

    def __str__(self):
        return self.title


class SubTask(models.Model):
    STATUS_CHOICES = [
        ("New", "New"),
        ("In progress", "In progress"),
        ("Done", "Done"),
    ]

    task = models.ForeignKey(
        Task,
        on_delete=models.CASCADE,
        related_name="subtasks"
    )
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default="New"
    )
    deadline = models.DateField(null=True, blank=True)

    def __str__(self):
        return f"{self.title} (task: {self.task.title})"

5. Миграции и git

python manage.py makemigrations tasks
python manage.py migrate

git init
git add .
git commit -m "feat: add Task and SubTask models"

Пошаговое решение с объяснением

Запустите Django Shell:

python manage.py shell

Шаг 1. Импорт зависимостей

from tasks.models import Task, SubTask
from datetime import date, timedelta

today = date.today()
print(f"Сегодня: {today}")

Импортируем модели (теория: Django Shell) и модуль datetime для работы с датами.

Шаг 2. Создание записей (Create)

# Создаём Task
task = Task.objects.create(
    title="Prepare presentation",
    description="Prepare materials and slides for the presentation",
    status="New",
    deadline=today + timedelta(days=3)
)
print(f"Task создан: id={task.id}, deadline={task.deadline}")

# SubTask 1
sub1 = SubTask.objects.create(
    task=task,
    title="Gather information",
    description="Find necessary information for the presentation",
    status="New",
    deadline=today + timedelta(days=2)
)

# SubTask 2
sub2 = SubTask.objects.create(
    task=task,
    title="Create slides",
    description="Create presentation slides",
    status="New",
    deadline=today + timedelta(days=1)
)

print(f"SubTask 1: id={sub1.id}")
print(f"SubTask 2: id={sub2.id}")

Используем create() — один шаг для создания и сохранения. Для SubTask передаём task=task — ссылку на родительскую задачу через ForeignKey (теория: create()).

Шаг 3. Чтение записей (Read)

# 3a. Task со статусом "New"
new_tasks = Task.objects.filter(status="New")
print(f"\nTask со статусом New ({new_tasks.count()} шт.):")
for t in new_tasks:
    print(f"  - {t.title} | deadline: {t.deadline}")

# 3b. SubTask со статусом "Done" и просроченным сроком
overdue_done = SubTask.objects.filter(
    status="Done",
    deadline__lt=today
)
print(f"\nПросроченные Done SubTask ({overdue_done.count()} шт.):")
for s in overdue_done:
    print(f"  - {s.title} | deadline: {s.deadline}")

filter(status="New") — стандартная фильтрация по точному значению. deadline__lt=today — lookup __lt (меньше чем), то есть срок истёк (теория: Lookups).

Шаг 4. Изменение записей (Update)

# 4a. Статус "Prepare presentation" → "In progress"
task = Task.objects.get(title="Prepare presentation")
task.status = "In progress"
task.save()
print(f"\nОбновлён статус: {task.title} → {task.status}")

# 4b. Срок "Gather information" → два дня назад
sub1 = SubTask.objects.get(title="Gather information")
sub1.deadline = today - timedelta(days=2)
sub1.save()
print(f"Обновлён deadline: {sub1.title} → {sub1.deadline}")

# 4c. Описание "Create slides"
sub2 = SubTask.objects.get(title="Create slides")
sub2.description = "Create and format presentation slides"
sub2.save()
print(f"Обновлено описание: {sub2.title}")

Шаблон: get() → изменить атрибут → save(). Метод get() бросает исключение, если запись не найдена (теория: get()).

Шаг 5. Удаление записей (Delete)

# Удаляем Task — SubTask удалятся каскадно (on_delete=CASCADE)
task = Task.objects.get(title="Prepare presentation")
deleted_count, details = task.delete()
print(f"\nУдалено объектов: {deleted_count}")
print(f"Подробно: {details}")

# Проверка — задачи больше нет
exists = Task.objects.filter(title="Prepare presentation").exists()
print(f"Task существует после удаления: {exists}")

delete() возвращает кортеж (количество_удалённых, словарь_по_типам). Поскольку в модели SubTask задан on_delete=models.CASCADE, подзадачи удаляются автоматически вместе с родительской задачей (теория: менеджер objects).

Проверка в VS Code

Запуск через терминал

  1. Откройте VS Code в папке проекта: code .
  2. Откройте встроенный терминал: Ctrl+` (backtick)
  3. Активируйте venv и запустите shell:
    .\venv\Scripts\Activate.ps1
    python manage.py shell
  4. Вставьте код решения поблочно и проверьте вывод

Запуск через F5 (launch.json)

Создайте файл .vscode/launch.json для запуска Django Shell через отладчик:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Django Shell",
      "type": "debugpy",
      "request": "launch",
      "program": "${workspaceFolder}/manage.py",
      "args": ["shell"],
      "django": true,
      "justMyCode": true,
      "console": "integratedTerminal"
    }
  ]
}

Нажмите F5 — откроется интерактивный shell с возможностью устанавливать точки останова в коде моделей.

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

  1. Создайте файл tasks/run_homework.py с кодом решения (оберните в функцию main())
  2. Кликните на номере строки в VS Code — появится красная точка (breakpoint)
  3. В launch.json измените args на ["shell", "-c", "exec(open('tasks/run_homework.py').read())"]
  4. Нажмите F5 — выполнение остановится на точке, можно инспектировать переменные

Скриншоты для сдачи

Сделайте скриншоты с выводом каждого шага:

  • Создание Task и SubTask — вывод ID
  • Фильтрация Task со статусом "New"
  • Поиск просроченных SubTask
  • Обновление статуса, дедлайна, описания
  • Удаление и подтверждение отсутствия записи

Связь с разделами курса

Действие в ДЗМетод/КонцепцияГде читать
Создание Task и SubTask objects.create() theory.html#create
Фильтрация по статусу filter(status="New") theory.html#filters
Просроченные задачи filter(deadline__lt=today) — lookup __lt theory.html#lookups
Изменение статуса get() → изменить → save() theory.html#get
Каскадное удаление on_delete=CASCADE, delete() examples.html
Все lookups __lt, __exact, __icontains... commands.html