Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Представления
views

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

Function-based views, Class-based views, Generic views, ViewSets

Представления в Django REST Framework

DRF предоставляет несколько уровней абстракции для представлений: от простых function-based views до мощных ViewSets с автоматическим роутингом.

#Function-Based Views с @api_view

Самый простой способ создать view в DRF — использовать декоратор @api_view:

from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status from .models import Article from .serializers import ArticleSerializer @api_view(['GET', 'POST']) def article_list(request): """ Список всех статей или создание новой. """ if request.method == 'GET': articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = ArticleSerializer(data=request.data) if serializer.is_valid(): serializer.save(author=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['GET', 'PUT', 'PATCH', 'DELETE']) def article_detail(request, pk): """ Получение, обновление или удаление статьи по ID. """ try: article = Article.objects.get(pk=pk) except Article.DoesNotExist: return Response( {'error': 'Статья не найдена'}, status=status.HTTP_404_NOT_FOUND ) if request.method == 'GET': serializer = ArticleSerializer(article) return Response(serializer.data) elif request.method == 'PUT': serializer = ArticleSerializer(article, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'PATCH': # Частичное обновление — только переданные поля serializer = ArticleSerializer(article, data=request.data, partial=True) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': article.delete() return Response(status=status.HTTP_204_NO_CONTENT)

Преимущества:

  • Простота и понятность
  • Полный контроль над логикой
  • Легко тестировать

Недостатки:

  • Много повторяющегося кода (boilerplate)
  • Нет автоматизации CRUD-операций

#Class-Based Views: APIView

Базовый класс для представлений в DRF:

from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class ArticleList(APIView): """ Список статей или создание новой. """ def get(self, request, format=None): articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = ArticleSerializer(data=request.data) if serializer.is_valid(): serializer.save(author=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class ArticleDetail(APIView): """ Получение, обновление или удаление статьи по ID. """ def get_object(self, pk): try: return Article.objects.get(pk=pk) except Article.DoesNotExist: return None def get(self, request, pk, format=None): article = self.get_object(pk) if article is None: return Response( {'error': 'Статья не найдена'}, status=status.HTTP_404_NOT_FOUND ) serializer = ArticleSerializer(article) return Response(serializer.data) def put(self, request, pk, format=None): article = self.get_object(pk) if article is None: return Response( {'error': 'Статья не найдена'}, status=status.HTTP_404_NOT_FOUND ) serializer = ArticleSerializer(article, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): article = self.get_object(pk) if article is None: return Response( {'error': 'Статья не найдена'}, status=status.HTTP_404_NOT_FOUND ) article.delete() return Response(status=status.HTTP_204_NO_CONTENT)

Преимущества перед function-based:

  • Легче расширять через наследование
  • Удобнее для сложной логики
  • Разделение методов HTTP по отдельным методам класса

#Generic Views

DRF предоставляет готовые классы для типовых операций:

from rest_framework import generics class ArticleList(generics.ListCreateAPIView): """ Список статей (GET) или создание новой (POST). """ queryset = Article.objects.all() serializer_class = ArticleSerializer def perform_create(self, serializer): # Автоматически устанавливаем автора serializer.save(author=self.request.user) class ArticleDetail(generics.RetrieveUpdateDestroyAPIView): """ Получение (GET), обновление (PUT/PATCH) или удаление (DELETE). """ queryset = Article.objects.all() serializer_class = ArticleSerializer

Готовые классы Generic Views:

КлассМетодыОписание
ListAPIViewGETСписок объектов (read-only)
CreateAPIViewPOSTСоздание объекта
ListCreateAPIViewGET, POSTСписок + создание
RetrieveAPIViewGETПолучение одного объекта (read-only)
UpdateAPIViewPUT, PATCHОбновление объекта
DestroyAPIViewDELETEУдаление объекта
RetrieveUpdateAPIViewGET, PUT, PATCHПолучение + обновление
RetrieveDestroyAPIViewGET, DELETEПолучение + удаление
RetrieveUpdateDestroyAPIViewGET, PUT, PATCH, DELETEПолный CRUD для одного объекта

#Mixins

Базовые классы, предоставляющие отдельные действия:

from rest_framework import mixins from rest_framework.generics import GenericAPIView class ArticleList(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class ArticleDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def patch(self, request, *args, **kwargs): return self.partial_update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs)

Миксины:

  • ListModelMixin — .list() для GET списка
  • CreateModelMixin — .create() для POST
  • RetrieveModelMixin — .retrieve() для GET одного объекта
  • UpdateModelMixin — .update() для PUT/PATCH
  • DestroyModelMixin — .destroy() для DELETE

#ViewSets

ViewSet объединяет логику для набора связанных views:

from rest_framework import viewsets class ArticleViewSet(viewsets.ModelViewSet): """ ViewSet для статей — предоставляет все CRUD-операции. """ queryset = Article.objects.all() serializer_class = ArticleSerializer def perform_create(self, serializer): serializer.save(author=self.request.user)

ModelViewSet автоматически предоставляет:

  • list() — GET списка
  • create() — POST создание
  • retrieve() — GET одного объекта
  • update() — PUT полное обновление
  • partial_update() — PATCH частичное обновление
  • destroy() — DELETE

Базовые классы ViewSets:

КлассДействия
ViewSetБазовый класс без готовых действий
GenericViewSetViewSet + GenericAPIView (queryset, serializer_class)
ModelViewSetПолный CRUD (list, create, retrieve, update, destroy)
ReadOnlyModelViewSetТолько чтение (list, retrieve)

#Кастомизация ViewSet

#Фильтрация queryset

class ArticleViewSet(viewsets.ModelViewSet): serializer_class = ArticleSerializer def get_queryset(self): """ Возвращает queryset, фильтруя по автору для не-админов. """ user = self.request.user if user.is_staff: return Article.objects.all() return Article.objects.filter(author=user) def perform_create(self, serializer): serializer.save(author=self.request.user)

#Разные сериализаторы для действий

class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all() def get_serializer_class(self): if self.action == 'list': return ArticleListSerializer elif self.action == 'retrieve': return ArticleDetailSerializer elif self.action == 'create': return ArticleCreateSerializer return ArticleSerializer

#Кастомные действия

from rest_framework.decorators import action from rest_framework.response import Response class ArticleViewSet(viewsets.ModelViewSet): queryset = Article.objects.all() serializer_class = ArticleSerializer @action(detail=True, methods=['post']) def publish(self, request, pk=None): """Публикация статьи.""" article = self.get_object() article.is_published = True article.save() return Response({'status': 'article published'}) @action(detail=False, methods=['get']) def recent(self, request): """Последние 5 статей.""" recent_articles = Article.objects.order_by('-created_at')[:5] serializer = self.get_serializer(recent_articles, many=True) return Response(serializer.data) @action(detail=True, methods=['get']) def comments(self, request, pk=None): """Комментарии к статье.""" article = self.get_object() comments = article.comments.all() return Response(CommentSerializer(comments, many=True).data)

Параметры @action:

  • detail=True — действие для одного объекта (/articles/{pk}/publish/)
  • detail=False — действие для коллекции (/articles/recent/)
  • methods — список разрешённых HTTP-методов
  • url_path — кастомный путь вместо имени метода
  • url_name — кастомное имя для reverse

#Выбор типа представления

ТипКогда использовать
@api_viewПростые endpoints, нестандартная логика
APIViewНужен полный контроль, сложная логика
GenericAPIView + MixinsСтандартные CRUD с кастомизацией
ViewSetRESTful API с полным CRUD, нужен автоматический роутинг
ModelViewSetБыстрое создание стандартного CRUD API

#Best Practices

  1. Используйте ModelViewSet для стандартных CRUD — это экономит код
  2. Переопределяйте get_queryset() вместо queryset = ... для избежания утечек данных между пользователями
  3. Используйте perform_create()/perform_update() для логики сохранения
  4. Кастомные действия через @action для нестандартных операций
  5. Разные сериализаторы для list/retrieve/create — оптимизирует вывод и валидацию

Далее: Роутинг