Какие есть составляющие компоненты у Django REST framework?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Основные компоненты Django REST Framework
Django REST Framework (DRF) — это один из самых популярных фреймворков для создания REST API на Python. Давайте разберёмся с его архитектурой и основными компонентами.
Архитектурные слои DRF
DRF строится на нескольких ключевых компонентах, которые работают вместе:
┌─────────────────────────────────────────────────────────┐
│ Views (APIView, ViewSets) │
│ Обработка HTTP запросов, вызов сериализаторов │
├─────────────────────────────────────────────────────────┤
│ Serializers (ModelSerializer, Serializer) │
│ Валидация, преобразование данных в/из JSON │
├─────────────────────────────────────────────────────────┤
│ Permissions, Authentication, Throttling │
│ Контроль доступа и безопасности │
├─────────────────────────────────────────────────────────┤
│ Models (Django ORM) │
│ Слой данных и бизнес логика │
└─────────────────────────────────────────────────────────┘
1. Views и ViewSets
APIView — базовый класс для создания API endpoints:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class UserListView(APIView):
"""Низкоуровневый контроль над endpoints"""
def get(self, request):
"""GET /users/"""
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def post(self, request):
"""POST /users/"""
serializer = UserSerializer(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)
ViewSets — высокоуровневая абстракция (как контроллер):
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
class UserViewSet(ModelViewSet):
"""Автоматически создаёт CRUD операции"""
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
"""Фильтрация по пользователю"""
return User.objects.filter(owner=self.request.user)
@action(detail=True, methods=['post'])
def activate(self, request, pk=None):
"""POST /users/{id}/activate/ — кастомный action"""
user = self.get_object()
user.is_active = True
user.save()
return Response({'status': 'user activated'})
# Один ViewSet автоматически создаёт:
# GET /users/ -> list()
# POST /users/ -> create()
# GET /users/{id}/ -> retrieve()
# PUT /users/{id}/ -> update()
# PATCH /users/{id}/ -> partial_update()
# DELETE /users/{id}/ -> destroy()
# POST /users/{id}/activate/ -> activate() (кастомный)
Регистрация маршрутов:
from rest_framework.routers import DefaultRouter
from django.urls import path, include
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
router.register(r'posts', PostViewSet, basename='post')
urlpatterns = [
path('api/v1/', include(router.urls)),
]
2. Serializers
Serializers — преобразуют объекты Django в JSON и обратно:
from rest_framework import serializers
from .models import User, Post
class UserSerializer(serializers.ModelSerializer):
"""Автоматический serializer из модели"""
email = serializers.EmailField() # Валидация email
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name', 'last_name']
read_only_fields = ['id'] # Только для чтения
extra_kwargs = {
'password': {'write_only': True}, # Не выводить в JSON
'username': {'required': True, 'allow_blank': False}
}
def validate_email(self, value):
"""Кастомная валидация email"""
if User.objects.filter(email=value).exists():
raise serializers.ValidationError("Email уже зарегистрирован")
return value
def create(self, validated_data):
"""Переопределить создание объекта"""
user = User.objects.create_user(**validated_data)
return user
Вложенные serializers:
class CommentSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True) # Вложенный serializer
class Meta:
model = Comment
fields = ['id', 'text', 'author', 'created_at']
class PostSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True, read_only=True)
author = UserSerializer(read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author', 'comments']
Общий Serializer (без модели):
class ContactSerializer(serializers.Serializer):
"""Для данных, которые не связаны с моделью"""
email = serializers.EmailField()
subject = serializers.CharField(max_length=200)
message = serializers.CharField()
def validate_email(self, value):
if not value.endswith(('@example.com',)):
raise serializers.ValidationError("Only example.com emails allowed")
return value
3. Authentication (Аутентификация)
Token Authentication:
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class ProtectedView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
# request.user содержит аутентифицированного пользователя
return Response({"user": str(request.user)})
# Клиент отправляет запрос с заголовком:
# Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
JWT Authentication:
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.views import TokenObtainPairView
class JWTProtectedView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({"message": "Hello authenticated user"})
# URL для получения токена
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view()),
]
# Клиент:
# 1. POST /api/token/ с username и password -> получает access и refresh токены
# 2. Authorization: Bearer <access_token>
4. Permissions (Разрешения)
Встроенные permissions:
from rest_framework.permissions import (
AllowAny, # Всем разрешено
IsAuthenticated, # Только аутентифицированным
IsAdminUser, # Только администраторам
IsAuthenticatedOrReadOnly, # Чтение всем, письмо только auth
)
class PublicView(APIView):
permission_classes = [AllowAny] # Всем доступ
def get(self, request):
return Response({"public": True})
class AdminView(APIView):
permission_classes = [IsAdminUser] # Только админы
def get(self, request):
return Response({"admin": True})
Кастомные permissions:
from rest_framework.permissions import BasePermission
class IsOwnerOrReadOnly(BasePermission):
"""Редактировать может только автор"""
def has_object_permission(self, request, view, obj):
# Чтение разрешено всем
if request.method in ['GET', 'HEAD', 'OPTIONS']:
return True
# Редактирование только если автор
return obj.owner == request.user
class PostDetailView(APIView):
permission_classes = [IsOwnerOrReadOnly]
def put(self, request, pk):
post = Post.objects.get(pk=pk)
self.check_object_permissions(request, post) # Проверяет разрешение
# ...
5. Throttling (Ограничение частоты)
Защита от DDoS и abuse:
from rest_framework.throttling import UserRateThrottle, AnonRateThrottle
class BurstRateThrottle(UserRateThrottle):
"""100 запросов в минуту для аутентифицированных"""
scope = 'burst'
THROTTLE_RATES = {
'burst': '100/minute',
'sustained': '1000/hour',
}
class AnonThrottle(AnonRateThrottle):
"""10 запросов в минуту для анонимных"""
scope = 'anon'
THROTTLE_RATES = {'anon': '10/minute'}
class LimitedView(APIView):
throttle_classes = [BurstRateThrottle, AnonThrottle]
def get(self, request):
return Response({"limited": True})
# Ответ с информацией о лимитах:
# HTTP/1.1 200 OK
# X-RateLimit-Limit: 100
# X-RateLimit-Remaining: 99
# X-RateLimit-Reset: 1234567890
6. Pagination (Постраничная выдача)
Встроенные paginator'ы:
from rest_framework.pagination import (
PageNumberPagination,
LimitOffsetPagination,
CursorPagination
)
class CustomPagination(PageNumberPagination):
page_size = 20
page_size_query_param = 'page_size'
max_page_size = 100 # Максимум на странице
class UserListView(ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
pagination_class = CustomPagination
# Запрос:
# GET /users/?page=2&page_size=50
# Ответ:
# {
# "count": 1000,
# "next": "http://example.com/users/?page=3",
# "previous": "http://example.com/users/?page=1",
# "results": [...]
# }
7. Filtering и Search
Встроенная фильтрация:
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
class UserListView(ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# Фильтрация по точным полям
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['is_active', 'date_joined']
# Поиск по полям
search_fields = ['username', 'email', 'first_name']
# Сортировка
ordering_fields = ['date_joined', 'username']
ordering = ['-date_joined']
# Запросы:
# GET /users/?is_active=true
# GET /users/?search=john
# GET /users/?ordering=-date_joined
8. Error Handling
Кастомные ошибки:
from rest_framework.exceptions import ValidationError, NotFound, PermissionDenied
class PostDetailView(APIView):
def get(self, request, pk):
try:
post = Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise NotFound(detail="Post not found")
if not post.is_published:
raise PermissionDenied(detail="Post is not published")
serializer = PostSerializer(post)
return Response(serializer.data)
# Ошибка 404:
# HTTP/1.1 404 Not Found
# {"detail": "Post not found"}
Полный пример микросервиса
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(ModelViewSet):
"""Полный CRUD для постов"""
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['author', 'published']
search_fields = ['title', 'content']
ordering = ['-created_at']
pagination_class = CustomPagination
def get_queryset(self):
"""Только свои посты для редактирования"""
if self.request.method in ['PUT', 'PATCH', 'DELETE']:
return Post.objects.filter(author=self.request.user)
return Post.objects.filter(published=True)
def perform_create(self, serializer):
"""Автоматически устанавливает автора"""
serializer.save(author=self.request.user)
Компоненты DRF — Сводная таблица
| Компонент | Назначение | Пример |
|---|---|---|
| Views | Обработка HTTP | APIView, ViewSets |
| Serializers | Валидация и преобразование | ModelSerializer |
| Authentication | Идентификация пользователя | TokenAuth, JWT |
| Permissions | Контроль доступа | IsAuthenticated |
| Throttling | Лимиты на запросы | RateThrottle |
| Pagination | Постраничная выдача | PageNumberPagination |
| Filtering | Поиск и фильтрация | DjangoFilterBackend |
| Renderers | Формат ответа | JSONRenderer |
| Exceptions | Обработка ошибок | ValidationError |
Заключение
Django REST Framework предоставляет полный набор инструментов для создания enterprise-grade REST API. Главные компоненты:
- Views/ViewSets — логика обработки запросов
- Serializers — валидация и преобразование данных
- Authentication — идентификация
- Permissions — авторизация
- Throttling — защита от перегруза
- Pagination — разбиение на страницы
- Filtering — поиск и фильтрация
Вместе они создают flexible и robust API framework.