JavaRush /Курсы /Модуль 3: Django /Использование ModelViewSet

Использование ModelViewSet

Модуль 3: Django
20 уровень , 3 лекция
Открыта

ModelViewSet – это один из самых удобных и часто используемых типов ViewSet в DRF. Он предназначен для работы с моделями Django и автоматически предоставляет полный набор операций CRUD (Create, Read, Update, Delete). По сути, он уже содержит всю необходимую логику, так что вам останется только подключить модель и сериализатор.

Почему ModelViewSet — это удобно?

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

Примерно как с хорошей библиотекой JavaScript: «просто подключи, и всё работает (почти)».

Как это работает?

ModelViewSet наследуется от класса GenericViewSet и смешивает в себе миксины, такие как CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin и ListModelMixin. Именно благодаря этим миксинам он предоставляет стандартные CRUD-операции.

Основной функционал, предоставляемый ModelViewSet:

  1. GET /items/ – возвращает список объектов.
  2. GET /items/<id>/ – возвращает объект с указанным ID.
  3. POST /items/ – создаёт новый объект.
  4. PUT /items/<id>/ – обновляет объект с указанным ID.
  5. PATCH /items/<id>/ – частично обновляет объект.
  6. DELETE /items/<id>/ – удаляет объект с указанным ID.

Реализация ModelViewSet

Теперь давайте перейдём от теории к практике. Мы создадим ModelViewSet для управления простой моделью — например, моделью задач для ToDo-приложения.

  1. Создадим модель Task

Сначала добавим новую модель в наш проект, если она ещё не была создана.

from django.db import models

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

    def __str__(self):
        return self.title

Не забудьте выполнить миграции:

python manage.py makemigrations
python manage.py migrate
  1. Создадим сериализатор для модели

Для работы ModelViewSet необходим сериализатор. Создадим простой TaskSerializer.

from rest_framework import serializers
from .models import Task

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = '__all__'

Сериализатор ModelSerializer автоматически генерирует поля на основе нашей модели, так что работа с ним сверхудобна.

  1. Создадим ModelViewSet

Теперь создадим сам ViewSet для модели Task. Это будет так же просто, как приготовить кофе из капсулы (если у вас есть кофемашина).

from rest_framework.viewsets import ModelViewSet
from .models import Task
from .serializers import TaskSerializer

class TaskViewSet(ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer

Обратите внимание:

  • queryset — это набор объектов, с которыми будет работать наш ViewSet.
  • serializer_class — указание сериализатора для обработки данных.
  1. Подключим маршрутизацию с Router

Настройка маршрутов для ViewSet выполняется через Router. Это делает нашу жизнь ещё проще.

Добавим маршруты в urls.py:

from rest_framework.routers import DefaultRouter
from .views import TaskViewSet

router = DefaultRouter()
router.register(r'tasks', TaskViewSet, basename='task')

urlpatterns = router.urls

Теперь DRF автоматически сгенерирует маршруты для работы с задачами, такие как:

  • GET /tasks/
  • POST /tasks/
  • GET /tasks/{id}/
  • PUT /tasks/{id}/
  • DELETE /tasks/{id}/

Попробуйте посетить /tasks/ в браузере или в Postman. У вас появится готовый API для управления задачами. Это, можно сказать, магия DRF.

Дополнительные возможности ModelViewSet

Всё это хорошо, но что, если вы захотите модифицировать стандартное поведение? Например, добавить проверку перед удалением задачи или отправлять письмо после её создания? Вам доступны следующие методы для переопределения:

  • list() — для обработки запроса на получение списка объектов (GET /tasks/).
  • retrieve() — для обработки запроса на получение одного объекта (GET /tasks/<id>/).
  • create() — для обработки запроса на создание объекта (POST /tasks/).
  • update() — для обработки запроса на обновление объекта (PUT/PATCH /tasks/<id>/).
  • destroy() — для обработки запроса на удаление объекта (DELETE /tasks/<id>/).

Пример переопределения метода destroy

Давайте добавим логику, которая запрещает удалять задачи, если они завершены.

from rest_framework.response import Response
from rest_framework import status

class TaskViewSet(ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer

    def destroy(self, request, *args, **kwargs):
        task = self.get_object()
        if task.completed:
            return Response(
                {"error": "Нельзя удалять завершённые задачи!"},
                status=status.HTTP_400_BAD_REQUEST
            )
        return super().destroy(request, *args, **kwargs)

Теперь при попытке удалить завершённую задачу API вернёт ошибку.

Когда использовать ModelViewSet?

ModelViewSet идеально подходит для стандартного CRUD-функционала, когда вам нужно быстро настроить API для работы с моделью. Однако, если у вас нестандартная логика, много кастомных действий, или вы хотите полностью контролировать процесс, лучше использовать APIView или GenericViewSet.

Практический пример

Попробуйте реализовать ModelViewSet для другой модели в вашем проекте. Например, если у вас есть модель пользователей или событий, настройте для неё ViewSet и проверьте работу через Postman. Как проверить?

  1. Создайте несколько задач через POST-запросы.
  2. Получите список всех задач через GET /tasks/.
  3. Завершите одну из задач (PATCH /tasks/1/ с параметром completed=true).
  4. Попробуйте удалить завершённую задачу и убедитесь, что сервер возвращает ошибку.

Типичные ошибки и их решения

Иногда вы можете столкнуться с такими ошибками:

  1. Ошибка маршрутизации: если вы добавили ViewSet к маршрутизатору неправильно, убедитесь, что использовали router.register() правильно.
  2. Ошибка в сериализаторе: если какие-то поля отсутствуют или не сериализуются, проверьте настройки вашего ModelSerializer.
  3. Проблемы с переопределением методов: убедитесь, что вы вызываете super() в переопределённых методах, чтобы не потерять стандартную логику.
1
Задача
Модуль 3: Django, 20 уровень, 3 лекция
Недоступна
Создание ModelViewSet для модели
Создание ModelViewSet для модели
1
Задача
Модуль 3: Django, 20 уровень, 3 лекция
Недоступна
Работа с моделью через ModelViewSet и создание кастомного действия
Работа с моделью через ModelViewSet и создание кастомного действия
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ