Гид по технологиям

Django Class-Based Views для CRUD: шаг за шагом в менеджере задач

6 min read Django Обновлено 31 Dec 2025
Django CBV: CRUD менеджер задач
Django CBV: CRUD менеджер задач

Иконки блокнота, книги, переработки и корзины для мусора, иллюстрирующие операции Create Read Update Delete

Что такое class-based views в Django

В Django представления (views) — это точки входа, которые принимают HTTP-запрос и возвращают HTTP-ответ. Class-based views (CBV) — это способ описывать представления классами вместо функций.

Преимущество CBV: лучше структурированный код, возможность наследования, переиспользование и встроенные методы для GET/POST и других операций. CBV упрощают создание стандартных CRUD-операций благодаря набору готовых классов (ListView, DetailView, CreateView, UpdateView, DeleteView и др.).

Определение в одну строку: CBV — это Python-классы, которые инкапсулируют логику обработки запросов и предоставляют переопределяемые методы для работы с формами, контекстом и перенаправлениями.

Важно: CBV не заменяют function-based views (FBV). Они дополняют инструментарий. Иногда FBV проще и прозрачнее для небольших эндпоинтов.

Встроенные class-based views в Django

Django содержит готовые CBV для типичных сценариев:

  • ListView — рендерит список объектов из модели.
  • DetailView — рендерит детальную страницу одного объекта.
  • CreateView — отображает форму и обрабатывает создание нового объекта.
  • UpdateView — отображает форму и обрабатывает обновление существующего объекта.
  • DeleteView — показывает страницу подтверждения и удаляет объект.
  • TemplateView — рендерит статичный шаблон с контекстом.
  • RedirectView — делает перенаправления.
  • FormView — упрощает обработку форм без прямой модели.

Каждый из этих классов можно конфигурировать через атрибуты (model, template_name, form_class, success_url и т. п.) и расширять через методы (get_queryset, get_context_data, form_valid и др.).

Когда CBV — хорошее решение и когда нет

Используйте CBV, если:

  • Вам нужны стандартные CRUD-интерфейсы.
  • Вы планируете реиспользовать логику через наследование.
  • Нужна аккуратная организация кода при росте приложения.

Выбирайте FBV, если:

  • Представление очень простое и одноразовое.
  • Нужна детальная логика, плохо укладывающаяся в шаблон CBV.

Контрпример: если вам надо написать одну простую страницу API-эндпоинта, которая возвращает JSON и содержит три строки кода, FBV будет короче и читабельнее.

Что мы построим

Приложение: менеджер задач (Task Manager). Функциональность:

  • список задач (Read list),
  • страница задачи (Read detail),
  • создание задачи (Create),
  • редактирование задачи (Update),
  • удаление задачи (Delete).

Дополнительно: в статье — чек-лист для ревьюера, критерии приёмки, тесты, мини-SOP по добавлению нового представления и decision tree для выбора между CBV и FBV.

Подготовка проекта

Шаги для создания проекта и приложения (дополненные инструкции и пояснения):

  1. Создайте виртуальное окружение и активируйте его. Для Unix/macOS:
python3 -m venv .venv
source .venv/bin/activate
  1. Установите Django:
pip install django
  1. Создайте проект project_core:
django-admin startproject project_core .
  1. Создайте приложение task_manager:
python manage.py startapp task_manager
  1. В settings.py добавьте ‘task_manager’ в INSTALLED_APPS:
INSTALLED_APPS = [
    # другие приложения
    'task_manager',
]
  1. Настройте корневые URLы project_core/urls.py, подключив маршруты приложения:
from django.urls import path, include

urlpatterns = [
    path('', include('task_manager.urls')),
]

Примечание: держите статические файлы и шаблоны настроенными для вашего окружения. Для быстрого старта используйте DEBUG=True и встроенный сервер разработки.

Модель Task

Создайте модель задачи в task_manager/models.py. Простая и понятная модель подходит для демонстрации CRUD:

from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Примените миграции:

python manage.py makemigrations && python manage.py migrate

Факт-бокс: модель содержит 4 поля: title, description, completed, created_at. created_at автоматически устанавливается при создании.

Форма для Create и Update

Создайте task_manager/forms.py:

from django import forms
from .models import Task

class TaskForm(forms.ModelForm):
    class Meta:
        model = Task
        fields = ['title', 'description', 'completed']
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'description': forms.Textarea(attrs={'class': 'form-control'}),
            'completed': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
        }

Пояснение: widgets помогают интегрировать фронтенд-стили (например, Bootstrap) без изменения логики формы.

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

Откройте task_manager/views.py и добавьте импорты и реализации CBV. Ниже — полный пример с комментариями.

from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Task
from .forms import TaskForm

class TaskListView(ListView):
    model = Task
    template_name = 'task_manager/task_list.html'
    context_object_name = 'tasks'
    paginate_by = 10  # добавили пагинацию по умолчанию

class TaskDetailView(DetailView):
    model = Task
    template_name = 'task_manager/task_detail.html'

class TaskCreateView(CreateView):
    model = Task
    form_class = TaskForm
    template_name = 'task_manager/task_form.html'
    success_url = reverse_lazy('task_list')

class TaskUpdateView(UpdateView):
    model = Task
    form_class = TaskForm
    template_name = 'task_manager/task_form.html'
    success_url = reverse_lazy('task_list')

class TaskDeleteView(DeleteView):
    model = Task
    template_name = 'task_manager/task_confirm_delete.html'
    success_url = reverse_lazy('task_list')

Пояснения по коду:

  • paginate_by в ListView улучшает UX при большом количестве задач.
  • reverse_lazy используется, потому что URL-конфигурация еще не загружена на момент импорта.

Маршруты (URLs)

Создайте task_manager/urls.py и опишите маршруты:

from django.urls import path
from .views import TaskListView, TaskDetailView, TaskCreateView, TaskUpdateView, TaskDeleteView

urlpatterns = [
    path('', TaskListView.as_view(), name='task_list'),
    path('create/', TaskCreateView.as_view(), name='task_create'),
    path('tasks//', TaskDetailView.as_view(), name='task_detail'),
    path('tasks//update/', TaskUpdateView.as_view(), name='task_update'),
    path('tasks//delete/', TaskDeleteView.as_view(), name='task_delete'),
]

Совет: для человеко-понятных URL можно заменить на и добавить поле slug в модель.

Шаблоны

Создайте шаблоны в task_manager/templates/task_manager/. Ниже — базовые примеры. Оставляем расширение base.html на ваше усмотрение.

task_list.html

{% extends 'base.html' %}

{% block content %}

Your Tasks

Add Task {% for task in tasks %}
{{ task.title }}

{{ task.description|truncatechars:50 }}

Completed: {% if task.completed %}Yes{% else %}No{% endif %}

Read more Delete task
{% empty %}

No tasks yet.

Add Task {% endfor %}
{% endblock %}

Список задач в приложении менеджера задач

task_detail.html

{% extends 'base.html' %}

{% block content %}

{{ task.title }}

{{ task.description }}

Completed: {% if task.completed %}Yes{% else %}No{% endif %}

Edit task Delete task {% endblock %}

Детальная страница задачи с описанием и статусом

task_form.html

{% extends 'base.html' %}

{% block content %}
  

Create Task

{% csrf_token %} {{ form.as_p }}
{% endblock %}

Форма для создания и редактирования задач

task_confirm_delete.html

{% extends 'base.html' %}

{% block content %}
  

Confirm Delete

Are you sure you want to delete "{{ object.title }}"?

{% csrf_token %} Cancel
{% endblock %}

Страница подтверждения удаления задачи

Совет по UX: добавьте предупреждение на JavaScript и undo через soft-delete для важных данных.

Расширение: добавление поиска и фильтрации

Чтобы позволить пользователю искать задачи, расширьте TaskListView:

class TaskListView(ListView):
    model = Task
    template_name = 'task_manager/task_list.html'
    context_object_name = 'tasks'
    paginate_by = 10

    def get_queryset(self):
        qs = super().get_queryset().order_by('-created_at')
        q = self.request.GET.get('q')
        if q:
            qs = qs.filter(title__icontains=q) | qs.filter(description__icontains=q)
        return qs

В шаблоне добавьте форму поиска:

Тесты и критерии приёмки

Критерии приёмки:

  • Страница списка возвращает код 200 и содержит список задач.
  • Создание задачи через CreateView создаёт запись в базе и редиректит на список.
  • UpdateView корректно меняет поля модели.
  • DeleteView удаляет задачу и перенаправляет на список.

Пример простого теста в task_manager/tests.py:

from django.test import TestCase
from django.urls import reverse
from .models import Task

class TaskViewsTest(TestCase):
    def test_create_and_list(self):
        resp = self.client.post(reverse('task_create'), {'title': 't1', 'description': 'd', 'completed': False})
        self.assertEqual(resp.status_code, 302)  # redirect
        resp = self.client.get(reverse('task_list'))
        self.assertContains(resp, 't1')

Мини-SOP: добавить новое представление на основе CBV

  1. Добавьте/обновите модель в models.py.
  2. Создайте миграцию и примените её.
  3. При необходимости добавьте форму в forms.py.
  4. Добавьте класс-представление в views.py, наследуя подходящий CBV.
  5. Добавьте маршрут в urls.py и имя URL.
  6. Создайте шаблон, использующий context_object_name или object.
  7. Напишите тесты и запустите их.
  8. Обновите документацию и CHANGELOG.

Decision tree: выбрать CBV или FBV

flowchart TD
  A[Нужно CRUD?] -->|Да| B[Использовать CBV]
  A -->|Нет| C[Небольшой эндпоинт]
  C --> D[Использовать FBV]
  B --> E[Нужна тонкая логика?]
  E -->|Да| F[Можно комбинировать: CBV с переопределением методов]
  E -->|Нет| G[Стандартная CBV]

Роли и чек-листы

Разработчик:

  • Модель соответствует требованиям.
  • Формы валидируют поля.
  • URLы имеют имена.
  • Тесты покрывают основные сценарии.

Код-ревьюер:

  • Представления читаемы и понятны.
  • Не дублируется логика (вынесена в mixin/utility).
  • Нет прямых SQL-запросов без причин.

DevOps/Инженер развёртывания:

  • Настроены статики и шаблоны для production.
  • Миграции в порядке и совместимы с резервным копированием БД.

Альтернативы и интеграции

  • FBV — проще для единичных маршрутов.
  • Django REST Framework — если нужен API; там используют ViewSet и GenericAPIView.
  • Использовать mixins и собственные базовые классы для общих сценариев (например, AuditMixin для логирования изменений).

Тонкости и возможные ошибки

  • reverse_lazy vs reverse: при импортах модулей используйте reverse_lazy в классовых переменных.
  • context_object_name: если не задано, ListView отдаёт объект под именем object_list.
  • в UpdateView и CreateView при form_valid можно дописать дополнительную логику (например, связывание с пользователем).

Пример переопределения form_valid:

class TaskCreateView(CreateView):
    # ...
    def form_valid(self, form):
        # можно установить автора: form.instance.owner = self.request.user
        return super().form_valid(form)

Тест-кейсы для приёмки

  • Создание задачи с пустым title должно выдавать ошибку валидации.
  • Попытка обновить несуществующую задачу должна вернуть 404.
  • Удаление задачи должно уменьшать счётчик объектов в базе.
  • Пагинация должна корректно отображать страницы при > paginate_by задач.

Безопасность и приватность

  • Используйте CSRF-токены в формах (Django делает это стандартно в шаблонах).
  • Ограничивайте доступ к CRUD-операциям через декораторы или mixin-ы (LoginRequiredMixin, PermissionRequiredMixin).
  • Для многопользовательских приложений проверяйте, что пользователь может изменять только свои задачи.

Пример ограничения доступа:

from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin

class TaskUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    # ...
    def test_func(self):
        return self.get_object().owner == self.request.user

Сценарии отказа и как их обрабатывать

  • Сбой БД: возвращать 5xx и показывать страницу с сообщением об ошибке.
  • Массовые операции удаления: использовать подтверждение и/или soft-delete.
  • Конфликт одновременных обновлений: внедрить optimistic locking (версия) или блокировки на уровне транзакции.

Итог и рекомендации

Class-based views отлично подходят для типичных CRUD-сценариев. Они ускоряют разработку, улучшают структуру кода и дают мощные точки расширения через наследование и mixin-ы. Используйте CBV для повторяемых шаблонов, и не стесняйтесь переключаться на FBV, если задача требует простой и прозрачной логики.

Важно: пишите тесты и определяйте критерии приёмки перед реализацией. Это уменьшит количество регрессий и ускорит код-ревью.

Summary:

  • CBV экономят время при создании CRUD-интерфейсов.
  • Для сложной логики комбинируйте CBV с переопределением методов.
  • Всегда добавляйте проверки доступа и тесты.

Important: перед деплоем проверьте настройки STATIC_ROOT, ALLOWED_HOSTS и конфигурацию базы данных.

Краткая шпаргалка по атрибутам CBV

  • model — модель, с которой работает представление.
  • template_name — шаблон для рендера.
  • context_object_name — имя переменной в контексте шаблона.
  • form_class — класс формы для Create/Update.
  • success_url — адрес для перенаправления после успешной операции.
  • paginate_by — размер страницы для ListView.

Конец статьи.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Kanban в Obsidian — руководство и шаблоны
Продуктивность

Kanban в Obsidian — руководство и шаблоны

Crunchyroll на Nintendo Switch — как скачать
Гайды

Crunchyroll на Nintendo Switch — как скачать

Как заполнить бесплатный OneDrive — идеи и шаблоны
Облачное хранилище

Как заполнить бесплатный OneDrive — идеи и шаблоны

Бейдж Facebook в подписи Mail на Mac
Инструкции

Бейдж Facebook в подписи Mail на Mac

Удалить OneDrive в Windows 10 и 8.1 — полная инструкция
Windows

Удалить OneDrive в Windows 10 и 8.1 — полная инструкция

Как не попасться на мошенников в Steam
Безопасность

Как не попасться на мошенников в Steam