Давайте договоримся: мы не будем писать избыточный boilerplate-код, если задачу можно автоматизировать. Django REST Framework предлагает нам прекрасный инструмент — Routers, которые облегчают настройку маршрутов для API. Сегодня мы познакомимся с двумя популярными реализациями Routers: SimpleRouter и DefaultRouter.
Что такое Router?
Router — это объект в Django REST Framework, который автоматически связывает ваш ViewSet с маршрутами URL. Например, если у нас есть модель Product и соответствующий ViewSet для неё, то Router может создать маршруты для работы с этим ресурсом (например, /products/ для списка продуктов и /products/<id>/ для работы с конкретным продуктом).
Чтобы вручную настроить маршруты для каждого ресурса в API нужно написать очень много кода. Это минимум четыре маршрута для CRUD-операций (Create, Retrieve, Update, Delete) плюс, возможно, маршруты для дополнительных кастомных действий. Routers избавляют вас от этой рутины — они автоматически создают маршруты для каждого метода вашего ViewSet.
Routers сканируют ваш ViewSet и определяют, какие стандартные маршруты (например, list, retrieve, create, update, destroy) должны быть созданы. Затем они генерируют соответствующие URL и добавляют их в маршруты вашего проекта.
SimpleRouter и DefaultRouter: в чём разница?
Итак, Django REST Framework предлагает несколько готовых реализаций Routers. Наиболее популярные из них — это SimpleRouter и DefaultRouter.
SimpleRouter, как следует из названия, — это базовая реализация Router. Он создаёт маршруты для стандартных методов ViewSet (CRUD), но не добавляет ничего лишнего. Если вы хотите, чтобы ваш API был минималистичным и не имел лишнего функционала, SimpleRouter — ваш выбор.
Пример использования SimpleRouter
Давайте посмотрим, как использовать SimpleRouter для настройки маршрутов.
from rest_framework.routers import SimpleRouter
from django.urls import path, include
from myapp.views import ProductViewSet
# Создаём SimpleRouter
router = SimpleRouter()
# Регистрируем ViewSet
router.register(r'products', ProductViewSet, basename='product')
# Подключаем маршруты
urlpatterns = [
path('', include(router.urls)),
]
Если вы зарегистрировали ProductViewSet с SimpleRouter, он создаст следующие маршруты:
| Маршрут | Метод HTTP | Описание |
|---|---|---|
/products/ |
GET | Список продуктов |
/products/ |
POST | Создание нового продукта |
/products/<id>/ |
GET | Получение отдельного продукта |
/products/<id>/ |
PUT | Полное обновление продукта |
/products/<id>/ |
PATCH | Частичное обновление продукта |
/products/<id>/ |
DELETE | Удаление продукта |
Как видно, этот Router создаёт только базовые маршруты.
DefaultRouter и пример его использования
DefaultRouter является более мощной версией Router и включает дополнительные возможности. Помимо стандартных маршрутов, он автоматически генерирует URL для корневого представления API (API root). Это представление можно использовать, чтобы увидеть список всех доступных ресурсов API. DefaultRouter идеально подходит для создания более информативных API.
Использование DefaultRouter почти идентично SimpleRouter. Разница лишь в том, что DefaultRouter добавляет корневое представление.
from rest_framework.routers import DefaultRouter
from django.urls import path, include
from myapp.views import ProductViewSet
# Создаём DefaultRouter
router = DefaultRouter()
# Регистрируем ViewSet
router.register(r'products', ProductViewSet, basename='product')
# Подключаем маршруты
urlpatterns = [
path('', include(router.urls)),
]
DefaultRouter добавляет все те же маршруты, что и SimpleRouter, но также добавляет корневой маршрут:
| Маршрут | Метод HTTP | Описание |
|---|---|---|
/ |
GET | Корневое представление API |
/products/ |
GET | Список продуктов |
/products/ |
POST | Создание нового продукта |
/products/<id>/ |
GET | Получение отдельного продукта |
/products/<id>/ |
PUT | Полное обновление продукта |
/products/<id>/ |
PATCH | Частичное обновление продукта |
/products/<id>/ |
DELETE | Удаление продукта |
Если вы перейдёте на корневой маршрут /, DefaultRouter предоставит вам JSON со списком всех зарегистрированных ViewSet. Это удобно для документации и тестирования API.
Таблица сравнения SimpleRouter и DefaultRouter
| Характеристика | SimpleRouter | DefaultRouter |
|---|---|---|
| Генерация базовых маршрутов | ✅ | ✅ |
| Поддержка API root | ❌ | ✅ |
| Простота использования | ✅ | ✅ |
Когда использовать SimpleRouter, а когда DefaultRouter?
Все зависит от ваших потребностей:
- SimpleRouter отлично подходит, если вам нужна компактность и минимализм в API. Это особенно актуально, если вы заботитесь о каждом байте или не нуждаетесь в корневом представлении API.
- DefaultRouter рекомендуется использовать в большинстве случаев, так как наличие корневого представления делает API более информативным. Это также полезно для начального этапа разработки, когда вы часто проверяете доступные эндпоинты.
Пример проекта с SimpleRouter и DefaultRouter
Давайте рассмотрим пример приложения, в котором используются оба Router.
Модели
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
Сериализаторы
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
ViewSet
from rest_framework.viewsets import ModelViewSet
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
Настройка маршрутов
from rest_framework.routers import SimpleRouter, DefaultRouter
from django.urls import path, include
from .views import ProductViewSet
# Создаём SimpleRouter
simple_router = SimpleRouter()
simple_router.register(r'simple-products', ProductViewSet, basename='simple-product')
# Создаём DefaultRouter
default_router = DefaultRouter()
default_router.register(r'products', ProductViewSet, basename='product')
# Подключаем оба Router
urlpatterns = [
path('simple/', include(simple_router.urls)),
path('default/', include(default_router.urls)),
]
Теперь у нас есть два разных маршрута:
/simple/simple-products/— минималистичный маршрут с использованием SimpleRouter./default/products/— маршрут с корневым представлением через DefaultRouter.
Попробуйте открыть /default/ в браузере, и вы увидите корневое представление API.
Типичные ошибки при использовании Routers
Часто новички сталкиваются с несколькими проблемами:
Отсутствие
basename. Если ваш ViewSet не имеет атрибутаqueryset, вы обязаны указатьbasenameпри регистрации в Router. Иначе вы получите ошибку.router.register(r'products', ProductViewSet) # Ошибка router.register(r'products', ProductViewSet, basename='product') # ПравильноДублирование маршрутов. Убедитесь, что разные Routers (например, SimpleRouter и DefaultRouter) не генерируют одинаковые маршруты, иначе вы вызовете конфликт.
Пропуск
include(router.urls). Если забыть подключить маршруты Router вurlpatterns, API просто не будет работать. Всегда проверяйте, чтоincludeиспользуется правильно.
И на заметку: DefaultRouter автоматически добавляет / к корневому маршруту. Если вы не хотите этого, используйте SimpleRouter.
На этом всё! Теперь, когда вы научились использовать SimpleRouter и DefaultRouter, можете создавать более удобные и оптимальные маршруты для ваших ViewSet, используя их лучшие стороны.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ