Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы роутинга в Django REST Framework
Даже опытные Django разработчики часто путаются в роутинге DRF. Существует несколько подходов от примитивных до самых изящных, и выбор зависит от сложности API.
1. Ручное определение URLs (базовый способ)
Самый явный способ — определить каждый endpoint вручную:
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('users/', views.UserListView.as_view(), name='user-list'),
path('users/<int:pk>/', views.UserDetailView.as_view(), name='user-detail'),
path('users/<int:pk>/posts/', views.UserPostsView.as_view(), name='user-posts'),
path('posts/', views.PostListView.as_view(), name='post-list'),
path('posts/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
]
Плюсы:
- Полный контроль
- Явное лучше неявного
Минусы:
- Много кода
- Легко ошибиться
- Сложно масштабировать
2. APIView с базовыми классами
Для простых CRUD операций DRF предоставляет миксины:
from rest_framework import generics
from .models import User, Post
from .serializers import UserSerializer, PostSerializer
class UserListView(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# GET /users/ — список
# POST /users/ — создание
class UserDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# GET /users/{id}/ — получить
# PUT /users/{id}/ — обновить
# DELETE /users/{id}/ — удалить
# urls.py
urlpatterns = [
path('users/', UserListView.as_view()),
path('users/<int:pk>/', UserDetailView.as_view()),
]
Плюсы:
- Стандартные CRUD операции
- Меньше кода
Минусы:
- Нет гибкости для кастомных endpoints
- Нужно создавать доп. классы для каждого ресурса
3. ViewSets и Router (рекомендуемый способ)
Это самый мощный и элегантный подход:
# views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import User, Post
from .serializers import UserSerializer, PostSerializer
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Автоматические CRUD endpoints:
# GET /users/ — список
# POST /users/ — создание
# GET /users/{id}/ — получить
# PUT /users/{id}/ — обновить
# DELETE /users/{id}/ — удалить
@action(detail=True, methods=['get'])
def posts(self, request, pk=None):
user = self.get_object()
posts = user.posts.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
@action(detail=False, methods=['post'])
def bulk_delete(self, request):
ids = request.data.get('ids', [])
User.objects.filter(id__in=ids).delete()
return Response({'status': 'deleted'})
class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
# urls.py
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'posts', views.PostViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Это автоматически создаст следующие endpoints:
GET /users/ — список пользователей
POST /users/ — создание пользователя
GET /users/{id}/ — получить пользователя
PUT /users/{id}/ — полное обновление
PATCH /users/{id}/ — частичное обновление
DELETE /users/{id}/ — удаление
GET /users/{id}/posts/ — посты пользователя
POST /users/bulk_delete/ — массовое удаление
4. Кастомный Router
Если нужны нестандартные URL паттерны:
from rest_framework.routers import SimpleRouter
class CustomRouter(SimpleRouter):
routes = [
DefaultRouter.routes[0], # {prefix}/ list/create
DefaultRouter.routes[1], # {prefix}/{lookup}/ retrieve/update/destroy
]
router = CustomRouter()
router.register(r'v1/users', UserViewSet)
5. Вложенные ресурсы (nested resources)
Определение иерархических relationships:
from rest_framework_nested import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet, basename='user')
posts_router = routers.NestedSimpleRouter(
router, 'users', lookup='user'
)
posts_router.register(r'posts', UserPostsViewSet, basename='user-posts')
urlpatterns = [
path('', include(router.urls)),
path('', include(posts_router.urls)),
]
# Результат:
# GET /users/{user_id}/posts/
# POST /users/{user_id}/posts/
# GET /users/{user_id}/posts/{id}/
6. Миксированный подход
Когда нужна комбинация подходов:
from rest_framework.routers import DefaultRouter
from django.urls import path, include
router = DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'posts', PostViewSet)
urlpatterns = [
# Автоматические маршруты
path('api/v1/', include(router.urls)),
# Ручные специальные endpoints
path('api/v1/admin/stats/', StatsView.as_view()),
path('api/v1/auth/login/', LoginView.as_view()),
path('api/v1/auth/logout/', LogoutView.as_view()),
]
7. Permissions и кастомная логика в router
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import permission_classes
class SecureUserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
if self.request.user.is_staff:
return User.objects.all()
return User.objects.filter(id=self.request.user.id)
def get_serializer_class(self):
if self.action == 'create':
return CreateUserSerializer
return UserSerializer
Сравнение подходов
| Способ | Сложность | CRUD | Кастомные | Масштабируемость |
|---|---|---|---|---|
| Ручные URLs | Высокая | Нет | Да | Низкая |
| generics | Средняя | Да | Средняя | Средняя |
| ViewSets + Router | Низкая | Да | Да | Высокая |
| Nested resources | Средняя | Да | Да | Высокая |
Best Practice
- Начни с ViewSets + Router — это стандарт
- Используй @action для кастомных endpoints
- Для сложных случаев — комбинируй с ручными URLs
- Вложенные ресурсы — через drf-nested-routers
- API версионирование — через URL префиксы
Выбор правильного роутинга сильно влияет на читаемость и масштабируемость API!