📖 Теория: Представления и маршруты DRF

⚡ Ключевые концепции

  • ModelViewSet — ViewSet с полным CRUD; регистрируется через Router
  • DefaultRouter — автоматически создаёт все URL (list, detail, create, update, delete)
  • ListCreateAPIView — GET (список) + POST (создание)
  • RetrieveUpdateDestroyAPIView — GET (деталь) + PUT/PATCH + DELETE
  • get_serializer_class() — возвращает разные сериализаторы по методу запроса
  • DjangoFilterBackend — фильтрация через query-параметры (?category=1&price=100)

ModelViewSet и DefaultRouter

ModelViewSet — самый высокоуровневый инструмент DRF для создания CRUD API. Один класс заменяет 5 отдельных представлений (list, create, retrieve, update, destroy).

from rest_framework import viewsets
from .models import Category
from .serializers import CategorySerializer

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

DefaultRouter автоматически генерирует маршруты:

from rest_framework.routers import DefaultRouter
from .views import CategoryViewSet

router = DefaultRouter()
router.register(r'categories', CategoryViewSet)

urlpatterns = [
    path('', include(router.urls)),
]
Что создаёт DefaultRouter:
  • GET /categories/ — список всех категорий
  • POST /categories/ — создание категории
  • GET /categories/{id}/ — получение категории по ID
  • PUT /categories/{id}/ — полное обновление
  • PATCH /categories/{id}/ — частичное обновление
  • DELETE /categories/{id}/ — удаление

Когда использовать ViewSet, а когда Generic Views

В этом практикуме используются оба подхода — в зависимости от требований модели:

Подход Когда подходит Модели в практикуме
ModelViewSet Один сериализатор на все операции Category, Supplier, Address
Generic Views Разные сериализаторы для GET и POST/PUT Product, ProductDetail, Customer, Order, OrderItem

Generic Views: ListCreateAPIView и RetrieveUpdateDestroyAPIView

Когда для GET и POST/PUT нужны разные сериализаторы (например, при чтении возвращаем вложенные объекты, при записи принимаем FK-ключи), используем Generic Views с переопределением get_serializer_class():

from rest_framework.generics import ListCreateAPIView
from .models import Product
from .serializers import ProductSerializer, ProductCreateUpdateSerializer

class ProductListCreateView(ListCreateAPIView):
    queryset = Product.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return ProductSerializer          # возвращает вложенные объекты
        return ProductCreateUpdateSerializer  # принимает FK-ключи

Для детального представления:

from rest_framework.generics import RetrieveUpdateDestroyAPIView

class ProductDetailUpdateDeleteView(RetrieveUpdateDestroyAPIView):
    queryset = Product.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return ProductSerializer
        return ProductCreateUpdateSerializer

URL для Generic Views регистрируются вручную:

from django.urls import path
from .views import ProductListCreateView, ProductDetailUpdateDeleteView

urlpatterns = [
    path('products/', ProductListCreateView.as_view()),
    path('products/<int:pk>/', ProductDetailUpdateDeleteView.as_view()),
]

DjangoFilterBackend и фильтрация

Для добавления фильтрации через query-параметры используется пакет django-filter:

# settings.py
INSTALLED_APPS = [
    # ...
    'django_filters',
]

# views.py
from django_filters.rest_framework import DjangoFilterBackend

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['category', 'price']

После настройки можно делать запросы: GET /api/products/?category=2&price=100

Установка django-filter: pip install django-filter. Затем обязательно добавить 'django_filters' в INSTALLED_APPS. Без этого шага DRF не увидит бекенд фильтрации.
← К оглавлению урока    Справочник →