Если посмотреть на работу веб-приложений в целом, маршрутизация определяет, какой обработчик будет вызван на конкретный запрос. Например, запрос GET /articles/1/ должен попасть на обработчик, который вернёт данные статьи с ID = 1. Вот где маршрутизация вступает в игру: она "прокладывает путь" между URL и вашим кодом.
В Django REST Framework маршрутизация берёт эти принципы и добавляет удобства: вы можете использовать как стандартные функции path() и re_path(), так и специальные маршрутизаторы (Routers), которые делают часть работы за нас. Разберёмся во всём по порядку.
Основы маршрутизации: связь URL с обработчиком
Начнём с базового подхода и будем использовать APIView. Например, предположим, что у нас есть простое приложение с моделью Article. Вот пример:
# models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
def __str__(self):
return self.title
Мы хотим создать API, чтобы получать список всех статей и добавлять новые. Для начала создадим два метода внутри представления APIView:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Article
from .serializers import ArticleSerializer
class ArticleListCreateAPIView(APIView):
def get(self, request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Теперь добавим маршруты для подключения к этим методам:
# urls.py
from django.urls import path
from .views import ArticleListCreateAPIView
urlpatterns = [
path('articles/', ArticleListCreateAPIView.as_view(), name='article-list-create'),
]
Сейчас наши запросы попадут к ArticleListCreateAPIView, и всё заработает. Но при увеличении количества представлений (например, добавлении обработки GET /articles/<id>/) код маршрутизации станет громоздким. Чтобы решить эту проблему, мы можем использовать ViewSet.
Использование ViewSet для упрощения маршрутизации
Вместо того чтобы прописывать маршруты для каждого метода, DRF предлагает создать ViewSet, который объединяет логику для однотипных операций. Вот пример ViewSet для нашего API:
# views.py
from rest_framework.viewsets import ModelViewSet
class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
Обратите внимание, как лаконично объявлена эта структура: DRF сам знает, что ViewSet должен поддерживать GET, POST, PUT, DELETE и т.д.
Теперь идём к маршрутам. Вместо ручного прописывания используем маршрутизатор:
# urls.py
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='article')
urlpatterns = router.urls
Благодаря этому мы получаем маршруты для всех CRUD-операций автоматически:
GET /articles/POST /articles/GET /articles/<id>/PUT /articles/<id>/DELETE /articles/<id>/
Нетрудно заметить, насколько это упрощает жизнь.
DefaultRouter и виды маршрутизаторов
DefaultRouter— это стандартный инструмент для автоматической генерации маршрутов. Он создаёт маршруты для списка, деталей и, что удобно, добавляет маршрут к корневому списку API. Это полезно для начальной настройки, но если у вас есть специфические требования, придётся всё-таки использовать кастомизации.SimpleRouter. Если корневой список API не нужен, вы можете использоватьSimpleRouterвместоDefaultRouter. Логика работы остаётся такой же, но он не добавляет "лишних" маршрутов.Custom Router. Для уникальных требований можно вообще создать свой маршрутизатор. DRF позволяет переопределить его поведение путём наследования отBaseRouter. Но в рамках большинства проектов важно освоить базовые варианты.
Комбинирование маршрутов вручную и с помощью Router
Иногда одни маршруты удобнее описывать явно, а другие подключать через маршрутизатор. Рассмотрим такой случай. Допустим, у нас есть ещё один эндпоинт, который возвращает "популярные статьи". Мы можем сделать следующее:
# views.py
from rest_framework.decorators import action
from rest_framework.response import Response
class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=False, methods=['get'])
def popular(self, request):
popular_articles = Article.objects.filter(is_popular=True)
serializer = self.get_serializer(popular_articles, many=True)
return Response(serializer.data)
В urls.py это выглядит так:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='article')
urlpatterns = [
path('', include(router.urls)),
path('articles/popular/', ArticleViewSet.as_view({'get': 'popular'})),
]
Теперь запрос GET /articles/popular/ вернёт популярные статьи.
Особенности и типичные ошибки
Когда работаешь с маршрутизацией, возникает ряд вопросов и потенциальный источник ошибок:
- Ошибка "NoReverseMatch". Если вы регистрируете маршруты через
DefaultRouter, убедитесь, что указали корректныйbasename. - Переопределение методов ViewSet. Если вам нужно определить кастомное поведение (например, разрешать удаление только админам), используйте методы ViewSet.
- Проблемы с включением маршрутизатора. Не забудьте про правильный импорт и подключение маршрутов с помощью
include(router.urls).
Практическое задание
Теперь, когда вы знаете, как использовать маршруты и маршрутизаторы, создайте API для управления задачами в приложении todo. Модель задачи должна содержать поля:
title(название задачи),description(описание),is_done(статус выполнения).
Реализуйте API для:
- Списка задач,
- Добавления новой задачи,
- Редактирования задачи,
- Удаления задачи,
- Маршрут
/tasks/completed/для получения выполненных задач.
Убедитесь, что ваш API протестирован с помощью браузера или Postman.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ