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

📋 Проект: Менеджер задач — продолжение

⚡ Что сделать (кратко)

  1. Добавить __str__ и Meta к моделям Task, SubTask, Category
  2. Настроить AdminClass для каждой модели в admin.py
  3. Создать суперпользователя и добавить объекты через Admin
  4. Создать коммит и запушить, прикрепить ссылку + скриншоты

Задание из LMS (оригинал)

Проект "Менеджер задач" — продолжение

Цель: Добавить строковое представление (__str__) и метаданные (Meta) к моделям менеджера задач, а также настроить административную панель для удобного управления этими моделями.

Реализуйте изменения в моделях:

Модель Task:

  • Добавить метод __str__, который возвращает название задачи.
  • Добавить класс Meta с настройками:
    • Имя таблицы в базе данных: 'task_manager_task'
    • Сортировка по убыванию даты создания
    • Человекочитаемое имя модели: 'Task'
    • Уникальность по полю 'title'

Модель SubTask:

  • Добавить метод __str__, который возвращает название подзадачи.
  • Добавить класс Meta с настройками:
    • Имя таблицы в базе данных: 'task_manager_subtask'
    • Сортировка по убыванию даты создания
    • Человекочитаемое имя модели: 'SubTask'
    • Уникальность по полю 'title'

Модель Category:

  • Добавить метод __str__, который возвращает название категории.
  • Добавить класс Meta с настройками:
    • Имя таблицы в базе данных: 'task_manager_category'
    • Человекочитаемое имя модели: 'Category'
    • Уникальность по полю 'name'

Настройте отображение моделей в Admin:

В файле admin.py вашего приложения добавьте классы администратора для настройки отображения моделей Task, SubTask и Category.

Зафиксируйте изменения в гит:

Создайте новый коммит и запушьте его в ваш гит.

Создайте записи через Admin:

  1. Создайте суперпользователя.
  2. Перейдите в административную панель Django.
  3. Добавьте несколько объектов для каждой модели.

Оформите ответ:

Прикрепите ссылку на гит и скриншоты, где видны созданные объекты, к ответу на домашнее задание.

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

1. Структура проекта

Убедитесь, что проект из ДЗ 8 (Урок 16) настроен и работает:

task_manager_project/
├── manage.py
├── task_manager_project/
│   ├── settings.py
│   └── urls.py
└── task_manager/
    ├── models.py       # Файл для изменений
    ├── admin.py        # Файл для изменений
    └── ...

2. Виртуальное окружение

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

# Установка зависимостей
pip install django

3. Проверка базы данных

# Убедитесь что база актуальна
python manage.py migrate

# Проверить текущее состояние
python manage.py showmigrations

Пошаговое решение

Шаг 1: Обновление models.py

Добавляем __str__ и Meta к каждой модели. Используем современный подход — UniqueConstraint вместо устаревшего unique_together.

Связь с теорией: метод __str__, класс Meta.

# task_manager/models.py
from django.db import models
from django.db.models import UniqueConstraint


class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        # Возвращаем название категории
        return self.name

    class Meta:
        db_table = 'task_manager_category'
        verbose_name = 'Category'
        verbose_name_plural = 'Categories'
        constraints = [
            UniqueConstraint(fields=['name'], name='unique_category_name'),
        ]


class Task(models.Model):
    STATUS_CHOICES = [
        ('new', 'Новая'),
        ('in_progress', 'В работе'),
        ('completed', 'Выполнена'),
    ]
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    categories = models.ManyToManyField(Category, blank=True)
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='new'
    )
    deadline = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        # Возвращаем название задачи
        return self.title

    class Meta:
        db_table = 'task_manager_task'
        ordering = ['-created_at']          # Сортировка по убыванию даты создания
        verbose_name = 'Task'
        verbose_name_plural = 'Tasks'
        constraints = [
            UniqueConstraint(fields=['title'], name='unique_task_title'),
        ]


class SubTask(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    task = models.ForeignKey(
        Task,
        on_delete=models.CASCADE,
        related_name='subtasks'
    )
    status = models.CharField(
        max_length=20,
        choices=Task.STATUS_CHOICES,
        default='new'
    )
    deadline = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        # Возвращаем название подзадачи
        return self.title

    class Meta:
        db_table = 'task_manager_subtask'
        ordering = ['-created_at']          # Сортировка по убыванию даты создания
        verbose_name = 'SubTask'
        verbose_name_plural = 'SubTasks'
        constraints = [
            UniqueConstraint(fields=['title'], name='unique_subtask_title'),
        ]
Примечание о unique_together vs UniqueConstraint: ДЗ требует «уникальность по полю» — это можно реализовать через unique=True на самом поле или через constraints. Используем constraints как современный подход. Если преподаватель проверяет именно unique_together — смотри Старый vs Новый.

Шаг 2: Создание и применение миграции

# Создаём миграцию для изменений в Meta
python manage.py makemigrations task_manager

# Применяем миграцию
python manage.py migrate

Если возникает конфликт из-за db_table — значит таблицы с такими именами уже существуют. В этом случае можно временно убрать db_table или выполнить ручную миграцию.

Шаг 3: Обновление admin.py

Создаём классы администратора для каждой модели и регистрируем через @admin.register.

Связь с теорией: Django Admin — ModelAdmin.

# task_manager/admin.py
from django.contrib import admin
from .models import Task, SubTask, Category


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    # Показываем название в списке
    list_display = ('name',)
    # Поиск по названию
    search_fields = ('name',)
    # Количество записей на странице
    list_per_page = 25


@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
    # Колонки в списке задач
    list_display = ('title', 'status', 'deadline', 'created_at')
    # Поиск по названию и описанию
    search_fields = ('title', 'description')
    # Фильтры справа: по статусу и категории
    list_filter = ('status', 'categories')
    # Сортировка: сначала новые
    ordering = ('-created_at',)
    # Количество задач на странице
    list_per_page = 25


@admin.register(SubTask)
class SubTaskAdmin(admin.ModelAdmin):
    # Колонки: название, родительская задача, дата создания
    list_display = ('title', 'task', 'status', 'created_at')
    # Поиск по названию
    search_fields = ('title',)
    # Фильтр по статусу и задаче
    list_filter = ('status', 'task')
    # Сортировка: сначала новые
    ordering = ('-created_at',)
    list_per_page = 25

Шаг 4: Создание суперпользователя

python manage.py createsuperuser

Django запросит:

  • Username (например: admin)
  • Email address (можно пустое)
  • Password (минимум 8 символов, не слишком простой)

Шаг 5: Добавление объектов через Admin

  1. Запустите сервер: python manage.py runserver
  2. Перейдите на http://127.0.0.1:8000/admin/
  3. Войдите с данными суперпользователя
  4. Добавьте несколько категорий (например: Работа, Личное, Обучение)
  5. Добавьте несколько задач с разными статусами
  6. Добавьте несколько подзадач к созданным задачам

Шаг 6: Коммит и push в Git

# Проверяем изменения
git status
git diff

# Добавляем изменённые файлы
git add task_manager/models.py task_manager/admin.py

# Добавляем файлы миграций
git add task_manager/migrations/

# Создаём коммит
git commit -m "feat: add __str__, Meta and AdminClass for Task, SubTask, Category"

# Пушим в удалённый репозиторий
git push origin main

Проверка в VS Code

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

  1. Откройте терминал: Ctrl+`
  2. Активируйте venv: venv\Scripts\activate
  3. Запустите сервер: python manage.py runserver
  4. Откройте браузер: http://127.0.0.1:8000/admin/

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

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

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

После создания файла нажмите F5 — Django запустится с поддержкой отладчика.

Точки останова (breakpoints) для отладки Admin

Для отладки Admin можно поставить breakpoint в admin.py:

  1. Откройте task_manager/admin.py
  2. Кликните на поле номера строки рядом с методом (например, list_display = ...) — появится красная точка
  3. Запустите через F5
  4. Откройте Admin в браузере — VS Code остановится на точке
Полезно: для отладки методов QuerySet в Admin удобно ставить breakpoint в методе get_queryset() класса ModelAdmin, если вы его переопределяете.

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

Что делаем в ДЗРаздел теорииПримеры
Метод __str__ Теория: __str__ Пример 1
Класс Meta: db_table, ordering, verbose_name Теория: класс Meta Пример 2, 3
Уникальность (UniqueConstraint) Справочник: constraints Пример 3
Классы AdminClass (ModelAdmin) Теория: Admin Пример 4, 6
@admin.register() Теория: регистрация Пример 4
createsuperuser Теория: суперпользователь Справочник: команды

Частые вопросы

Что если миграция конфликтует из-за db_table?

Если таблица уже существует под именем, которое задаёт db_table, то при migrate Django попытается переименовать её. Убедитесь, что имена совпадают с теми, что были созданы в ДЗ 8, или выполните:

python manage.py migrate --run-syncdb
Нужно ли добавлять unique=True к полю или использовать constraints?

Оба варианта корректны. unique=True прямо на поле — более компактно для одиночного поля. UniqueConstraint в constraints — современный и гибкий способ, позволяет задать имя ограничения. Если в условии ДЗ нет указания, используйте UniqueConstraint как best practice.

Не вижу модель в Admin — что не так?

Проверьте:

  1. Модель зарегистрирована в admin.py (через register или @admin.register)
  2. Приложение добавлено в INSTALLED_APPS в settings.py
  3. Выполнена команда python manage.py migrate
  4. Перезапустите сервер после изменений в admin.py