Давайте домовимось: ми не будемо писати зайвий 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, використовуючи їх найкращі сторони.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ