🏠 Домашнее задание: Расширение Library Project

⚡ Суть домашнего задания

Расширьте проект Library: добавьте модель Tag для тегирования книг (ManyToMany), модель ReadingList (список чтения пользователя), метод на Author для полного имени и зарегистрируйте всё в Admin.

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

Задание A: Модель Tag

Добавьте модель Tag для гибкой маркировки книг.

Поля:

  • name — CharField, макс. 50, уникальный
  • slug — SlugField, макс. 50, уникальный (для URL)

Связь: Добавьте в Book поле tags = ManyToManyField(Tag, blank=True, related_name='books').

Зарегистрируйте Tag в Admin.

Задание B: Модель ReadingList

Создайте модель «Список чтения» — личная полка пользователя.

Поля:

  • member — ForeignKey на Member (один участник → много списков)
  • title — CharField, макс. 100 (название списка: «Хочу прочитать», «Читаю сейчас»)
  • books — ManyToManyField на Book
  • created_at — DateField с auto_now_add=True
  • is_public — BooleanField, default=False (публичный список)

Добавьте __str__ и class Meta (verbose_name, ordering по дате).

Задание C: Метод на Author

Добавьте метод full_name() в модель Author, который возвращает полное имя: "{first_name} {last_name}".

Убедитесь, что __str__ и full_name() возвращают разные форматы.

Задание D: Улучшение Admin

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

  • Author: list_display = ('first_name', 'last_name', 'rating', 'deleted'), list_filter = ('deleted',), search_fields = ('first_name', 'last_name')
  • Book: list_display = ('title', 'author_id', 'genre', 'publishing_date'), list_filter = ('genre',)
  • Member: list_display = ('first_name', 'last_name', 'email', 'role', 'active'), list_filter = ('role', 'active')

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

# 1. Создать виртуальное окружение
python -m venv venv

# Windows PowerShell:
venv\Scripts\Activate.ps1

# Linux / macOS:
source venv/bin/activate

# 2. Установить Django
pip install django

# 3. Убедиться, что проект из практикума запущен
python manage.py check  # не должно быть ошибок

# 4. После добавления новых моделей:
python manage.py makemigrations
python manage.py migrate

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

Шаг 1: Модель Tag

# library/models.py — добавить:

class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)
    slug = models.SlugField(max_length=50, unique=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Тег"
        verbose_name_plural = "Теги"


# В классе Book добавить поле:
class Book(models.Model):
    ...
    tags = models.ManyToManyField(Tag, blank=True, related_name='books')

Шаг 2: Модель ReadingList

class ReadingList(models.Model):
    member = models.ForeignKey(Member, on_delete=models.CASCADE, related_name='reading_lists')
    title = models.CharField(max_length=100)
    books = models.ManyToManyField(Book, related_name='reading_lists')
    created_at = models.DateField(auto_now_add=True)
    is_public = models.BooleanField(default=False)

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

    class Meta:
        verbose_name = "Список чтения"
        verbose_name_plural = "Списки чтения"
        ordering = ['-created_at']

Шаг 3: Метод full_name

class Author(models.Model):
    ...
    def full_name(self):
        return f"{self.first_name} {self.last_name}"

    def __str__(self):
        # Краткий формат для Admin
        return f"{self.first_name} {self.last_name[0]}."

Шаг 4: Настройка Admin

# library/admin.py
from django.contrib import admin
from .models import Author, Book, Member, Tag, ReadingList

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'rating', 'deleted')
    list_filter = ('deleted',)
    search_fields = ('first_name', 'last_name')

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author_id', 'genre', 'publishing_date')
    list_filter = ('genre',)

@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email', 'role', 'active')
    list_filter = ('role', 'active')

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    list_display = ('name', 'slug')
    prepopulated_fields = {'slug': ('name',)}

admin.site.register(ReadingList)

Применение и проверка

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

Проверка в VS Code

  1. Откройте проект в VS Code
  2. В терминале активируйте venv и запустите python manage.py runserver
  3. Откройте http://127.0.0.1:8000/admin/ — убедитесь, что видите новые модели
  4. Создайте несколько тегов через Admin, назначьте их книгам
  5. Создайте ReadingList через Admin

Точки останова в VS Code (launch.json)

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

Нажмите F5 в VS Code — Django запустится в режиме отладки. Установите точку останова в любом методе модели (например, в __str__) и обратитесь к Admin — отладчик остановится там.

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