← Назад к вопросам

Какие знаешь способы роутинга в DRF?

1.3 Junior🔥 61 комментариев
#Django

Комментарии (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!

Какие знаешь способы роутинга в DRF? | PrepBro