Представления на основе классов

⏱ 25 мин · 🧩 заданий: 5

CBV изнутри

В блоге мы использовали ListView, почти не заглядывая внутрь. В этом проекте почти все страницы будут на классах, поэтому разберёмся, как они устроены.

as_view()

path("", ArticleListView.as_view(), name="home")

as_view() — classmethod, который возвращает функцию. На каждый запрос эта функция:

  1. создаёт новый экземпляр класса (поэтому хранить состояние в self безопасно);
  2. вызывает setup(request, *args, **kwargs) — сохраняет self.request, self.args, self.kwargs;
  3. вызывает dispatch(), который по методу запроса вызывает get(), post() и т. д., или отвечает 405.

Атрибуты можно передать прямо в as_view(): TemplateView.as_view(template_name="about.html").

Иерархия generic views

Класс Назначение
View База: dispatch, методы HTTP
TemplateView Отрисовать шаблон
RedirectView Перенаправить
ListView Список объектов, пагинация
DetailView Один объект по pk или slug
FormView Форма без модели
CreateView Создание объекта через ModelForm
UpdateView Редактирование
DeleteView Удаление с подтверждением

Каждый собран из миксинов: например, ListView = MultipleObjectTemplateResponseMixin + BaseListView (= MultipleObjectMixin + View). Подробную карту всех атрибутов и методов удобно смотреть на сайте ccbv.co.uk.

Жизненный цикл ListView

get()
 ├── self.object_list = get_queryset()
 ├── context = get_context_data(object_list=...)
 │      ├── paginate_queryset() (если paginate_by)
 │      └── context_object_name
 └── render_to_response(context)
        └── get_template_names()

Главные точки расширения

Метод / атрибут Что меняет
model, queryset Откуда брать объекты
get_queryset() Динамический набор (фильтр по URL, пользователю)
get_context_data() Дополнительные переменные в шаблоне
template_name, get_template_names() Шаблон
context_object_name Имя объекта/списка в шаблоне
paginate_by Пагинация
get_object() Как найти объект (DetailView и др.)
dispatch() Логика до обработки (проверки доступа)

Пример — главная страница сайта статей:

from django.views.generic import ListView

from .models import Article


class ArticleListView(ListView):
    model = Article
    template_name = "blog/articles_list.html"
    context_object_name = "articles"
    paginate_by = 6

    def get_queryset(self):
        return Article.custom.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["title"] = "Главная страница"
        return context

Всегда вызывайте super() в get_context_data — иначе потеряете контекст, который собирают родительские классы (список объектов, пагинацию).

Миксины

Миксин — маленький класс с одной функцией, который «подмешивают» к представлению:

class TitleMixin:
    title = None

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["title"] = self.title
        return context


class ArticleListView(TitleMixin, ListView):
    title = "Главная страница"
    ...

Миксины ставят левее базового представления: Python ищет методы слева направо (MRO), а super() передаёт управление дальше по цепочке. Встроенные миксины Django: LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin, SuccessMessageMixin. Свои миксины напишем в отдельном уроке.

Итог

  • as_view() → новый экземпляр → setup() → dispatch() → get()/post().
  • Generic views собраны из миксинов; главные точки расширения — get_queryset, get_context_data, get_object, dispatch.
  • В переопределённых методах вызывайте super().
  • Миксины добавляют функциональность через множественное наследование и ставятся слева.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Расставить по порядку

Расставьте этапы обработки запроса представлением-классом (ListView).

  1. dispatch() выбирает метод по HTTP-методу — get()
  2. Создаётся экземпляр класса, вызывается setup() (сохраняет request, args, kwargs)
  3. get_context_data() собирает контекст
  4. render_to_response() рендерит get_template_names()
  5. get() вызывает get_queryset()
  6. as_view() создаёт функцию, которую вызывает диспетчер URL
Задание 2 Один вариант ответа

Какой метод переопределить, чтобы добавить в шаблон дополнительную переменную title?

Задание 3 Написать код

Переопределите get_context_data во view, добавив в контекст title со значением "Главная страница". Не забудьте вызвать родительский метод.

Задание 4 Несколько вариантов

Какие классы — это generic views Django для работы с объектами?

Задание 5 Один вариант ответа

Что такое миксин (mixin)?

Войдите, чтобы отмечать пройденные уроки.