Текст задания из LMS
Источник: lms.itcareerhub.de — Python Adv 15: Модели Django
Проект «Менеджер задач»
Цель: Создать структуру менеджера задач и зарегистрировать модели в панели администратора Django.
Реализовать модели:
Модель Task
Описание: Задача для выполнения.
Поля:
- title — Название задачи. Уникально для даты (
unique_for_date). - description — Описание задачи.
- categories — Категории задачи. Многие ко многим.
- status — Статус задачи. Выбор из: New, In progress, Pending, Blocked, Done.
- deadline — Дата и время дедлайна.
- created_at — Дата и время создания. Автоматическое заполнение.
Модель SubTask
Описание: Отдельная часть основной задачи (Task).
Поля:
- title — Название подзадачи.
- description — Описание подзадачи.
- task — Основная задача. Один ко многим (ForeignKey).
- status — Статус задачи. Выбор из: New, In progress, Pending, Blocked, Done.
- deadline — Дата и время дедлайна.
- created_at — Дата и время создания. Автоматическое заполнение.
Модель Category
Описание: Категория выполнения.
Поля:
- name — Название категории.
Шаги для выполнения задания:
- Создайте модели: В файле
models.pyвашего приложения добавьте модели с указанными полями и описаниями. - Создайте миграции: Выполните команду для создания миграций:
python manage.py makemigrations - Примените миграции: Выполните команду для применения миграций:
python manage.py migrate - Зарегистрируйте модели в Admin: В файле
admin.pyвашего приложения зарегистрируйте все модели. - Зафиксируйте изменения в git: Создайте новый коммит и загрузите его в репозиторий.
- Создайте записи через Admin:
- Создайте суперпользователя.
- Перейдите в административную панель Django.
- Добавьте несколько объектов для каждой модели.
- Оформите ответ: Прикрепите ссылку на git и скриншоты, где видны созданные объекты.
Подготовка окружения
Шаг 0: Создать папку проекта (если ещё не создана)
# В PowerShell:
mkdir task-manager-project
cd task-manager-project
Шаг 1: Инициализировать git
git init
git checkout -b lesson/16-django-models
Шаг 2: Создать виртуальное окружение
# Создать venv
python -m venv .venv
# Активировать (Windows PowerShell):
.venv\Scripts\activate
# Активировать (Mac/Linux):
source .venv/bin/activate
Шаг 3: Установить Django
pip install django
# Зафиксировать зависимости
pip freeze > requirements.txt
Шаг 4: Создать Django-проект и приложение
# Создать проект (создаст папку task_manager_project/)
django-admin startproject task_manager_project .
# Создать приложение tasks
python manage.py startapp tasks
Шаг 5: Добавить приложение в INSTALLED_APPS
# task_manager_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tasks', # ← добавить!
]
Шаг 6: Создать .gitignore
# .gitignore
.venv/
__pycache__/
*.pyc
*.pyo
db.sqlite3
*.log
.env
Пошаговое решение
Шаг 1: Написать модели (tasks/models.py)
Логика проектирования:
- Category объявляем первой — на неё ссылается Task через ManyToMany.
- Task объявляем до SubTask — SubTask ссылается на Task через ForeignKey.
- Статусы вынесем в отдельный класс, чтобы не дублировать в Task и SubTask.
created_atсauto_now_add=True— заполняется автоматически при создании.unique_for_date='deadline'для title в Task — нельзя создать две задачи с одинаковым названием на одну дату.
# tasks/models.py
from django.db import models
class Category(models.Model):
"""Категория задачи."""
name = models.CharField(
max_length=100,
verbose_name='Название категории'
)
def __str__(self):
return self.name
class Meta:
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
ordering = ['name']
class Task(models.Model):
"""Основная задача для выполнения."""
# Статусы вынесены в TextChoices — современный Django 5.x подход
class Status(models.TextChoices):
NEW = 'new', 'New'
IN_PROGRESS = 'in_progress', 'In progress'
PENDING = 'pending', 'Pending'
BLOCKED = 'blocked', 'Blocked'
DONE = 'done', 'Done'
# title уникально для даты дедлайна: нельзя создать 2 задачи
# с одинаковым названием на одну дату
title = models.CharField(
max_length=200,
unique_for_date='deadline',
verbose_name='Название задачи'
)
description = models.TextField(
blank=True,
verbose_name='Описание'
)
# ManyToMany — одна задача может относиться ко многим категориям
categories = models.ManyToManyField(
Category,
blank=True,
related_name='tasks',
verbose_name='Категории'
)
status = models.CharField(
max_length=20,
choices=Status.choices,
default=Status.NEW,
verbose_name='Статус'
)
# DateTimeField — дата и время дедлайна
deadline = models.DateTimeField(
null=True,
blank=True,
verbose_name='Дедлайн'
)
# auto_now_add=True — заполняется автоматически при создании объекта
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата создания'
)
def __str__(self):
return f"{self.title} [{self.get_status_display()}]"
class Meta:
verbose_name = 'Задача'
verbose_name_plural = 'Задачи'
ordering = ['-created_at']
class SubTask(models.Model):
"""Подзадача — часть основной задачи."""
class Status(models.TextChoices):
NEW = 'new', 'New'
IN_PROGRESS = 'in_progress', 'In progress'
PENDING = 'pending', 'Pending'
BLOCKED = 'blocked', 'Blocked'
DONE = 'done', 'Done'
title = models.CharField(
max_length=200,
verbose_name='Название подзадачи'
)
description = models.TextField(
blank=True,
verbose_name='Описание'
)
# ForeignKey — одна Task имеет много SubTask
# CASCADE — при удалении Task все её SubTask тоже удаляются
task = models.ForeignKey(
Task,
on_delete=models.CASCADE,
related_name='subtasks',
verbose_name='Основная задача'
)
status = models.CharField(
max_length=20,
choices=Status.choices,
default=Status.NEW,
verbose_name='Статус'
)
deadline = models.DateTimeField(
null=True,
blank=True,
verbose_name='Дедлайн'
)
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата создания'
)
def __str__(self):
return f"{self.title} (задача: {self.task.title})"
class Meta:
verbose_name = 'Подзадача'
verbose_name_plural = 'Подзадачи'
ordering = ['-created_at']
Шаг 2: Зарегистрировать модели в Admin (tasks/admin.py)
Логика: регистрируем все три модели. Для Task добавляем отображение категорий и статуса в списке.
# tasks/admin.py
from django.contrib import admin
from .models import Category, Task, SubTask
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name',)
search_fields = ('name',)
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('title', 'status', 'deadline', 'created_at')
list_filter = ('status',)
search_fields = ('title', 'description')
filter_horizontal = ('categories',) # удобный виджет для M2M
ordering = ('-created_at',)
@admin.register(SubTask)
class SubTaskAdmin(admin.ModelAdmin):
list_display = ('title', 'task', 'status', 'deadline', 'created_at')
list_filter = ('status',)
search_fields = ('title', 'description')
ordering = ('-created_at',)
Шаг 3: Создать и применить миграции
# Создать файлы миграций
python manage.py makemigrations tasks
# Ожидаемый вывод:
# Migrations for 'tasks':
# tasks\migrations\0001_initial.py
# - Create model Category
# - Create model Task
# - Create model SubTask
# Применить миграции к БД
python manage.py migrate
# Ожидаемый вывод:
# ...
# Applying tasks.0001_initial... OK
Шаг 4: Создать суперпользователя
python manage.py createsuperuser
# Username: admin
# Email: admin@example.com
# Password: (введите надёжный пароль)
# Password (again): (повторите)
# Superuser created successfully.
Шаг 5: Запустить сервер и проверить Admin
python manage.py runserver
# Сервер запущен: http://127.0.0.1:8000/admin/
Откройте браузер → http://127.0.0.1:8000/admin/ → войдите с логином/паролем суперпользователя.
Шаг 6: Создать тестовые данные
В Admin создайте хотя бы:
- 2-3 категории (например: «Работа», «Личное», «Учёба»)
- 2-3 задачи с разными статусами, категориями и дедлайнами
- 1-2 подзадачи для каждой задачи
Шаг 7: Зафиксировать в git
git add tasks/models.py tasks/admin.py tasks/migrations/
git add requirements.txt .gitignore task_manager_project/settings.py
git commit -m "lesson 16: Task Manager — models Task, SubTask, Category + Admin"
git push origin lesson/16-django-models
Проверка в VS Code
Открыть проект
- Откройте VS Code.
- Меню File → Open Folder → выберите папку
task-manager-project. - VS Code предложит установить расширения Python — нажмите Install All.
Выбрать интерпретатор
- Нажмите Ctrl+Shift+P → введите Python: Select Interpreter.
- Выберите интерпретатор из
.venv.
Настройка launch.json для запуска Django (F5)
Создайте файл .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Django: runserver",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver"],
"django": true,
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}"
}
}
]
}
Нажмите F5 — Django запустится в режиме отладки. Браузер: http://127.0.0.1:8000/admin/
Точки останова в models.py
- Откройте
tasks/models.pyв VS Code. - Поставьте breakpoint на метод
__str__модели Task (кликните на номер строки). - Нажмите F5 → откройте Admin → откройте список задач.
- VS Code остановится на точке — в панели «Variables» можно увидеть
self.title,self.status. - F10 — шаг вперёд. F5 — продолжить до следующего breakpoint.
Отладка через Django shell
Для проверки моделей без запуска сервера используйте shell:
# В терминале VS Code (Ctrl+`):
python manage.py shell
# Проверить модели:
from tasks.models import Category, Task, SubTask
# Создать категорию
cat = Category(name='Работа')
cat.save()
print(Category.objects.all())
# Создать задачу
from django.utils import timezone
task = Task(title='Изучить Django', status='new', deadline=timezone.now())
task.save()
task.categories.add(cat)
task.save()
print(Task.objects.all())
print(task.categories.all())
Типичные ошибки при выполнении ДЗ
Ошибка: No module named 'django'
# venv не активирован. Активируйте:
.venv\Scripts\activate # Windows PowerShell
source .venv/bin/activate # Mac/Linux
pip install django
Ошибка: makemigrations не видит модели
Приложение tasks не добавлено в INSTALLED_APPS. Добавьте 'tasks' в список.
Ошибка: ManyToManyField через M2M без blank=True требует значения
# Неверно:
categories = models.ManyToManyField(Category) # форма требует категорию
# Верно для необязательных M2M:
categories = models.ManyToManyField(Category, blank=True)
Ошибка: ForeignKey без on_delete
# Неверно:
task = models.ForeignKey(Task) # TypeError в Django 5.x
# Верно:
task = models.ForeignKey(Task, on_delete=models.CASCADE)
Ошибка: unique_for_date требует DateTimeField с соответствующим именем
# unique_for_date='deadline' означает: title уникально для значения поля deadline
# Поле deadline должно быть DateField или DateTimeField
title = models.CharField(max_length=200, unique_for_date='deadline')
deadline = models.DateTimeField(null=True, blank=True) # должно существовать!
Как сдать задание
- Убедитесь, что
python manage.py runserverзапускается без ошибок. - Войдите в Admin (
http://127.0.0.1:8000/admin/) и убедитесь, что модели Task, SubTask, Category видны. - Создайте как минимум 2 категории, 2 задачи, 2 подзадачи через Admin.
- Сделайте скриншоты списков объектов в Admin.
- Добавьте файлы в git и создайте коммит:
git add tasks/models.py tasks/admin.py tasks/migrations/ git add requirements.txt .gitignore git commit -m "lesson 16: Task Manager — models + Admin" git push origin lesson/16-django-models - Вставьте ссылку на репозиторий и прикрепите скриншоты в LMS.