Что такое DRF
Django REST Framework (DRF) — это мощный инструмент для создания REST API на Django. Он предоставляет сериализаторы, viewsets, аутентификацию, разрешения и автоматическую документацию.
▸Установка
1pip install djangorestframework
▸Настройка
1# settings.py2INSTALLED_APPS = [3 'rest_framework',4 'myapp',5]67REST_FRAMEWORK = {8 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',9 'PAGE_SIZE': 20,10 'DEFAULT_AUTHENTICATION_CLASSES': [11 'rest_framework.authentication.TokenAuthentication',12 ],13}
Сериализаторы
▸Базовый сериализатор
1# serializers.py2from rest_framework import serializers3from .models import User45class UserSerializer(serializers.ModelSerializer):6 class Meta:7 model = User8 fields = ['id', 'name', 'email', 'created_at']9 read_only_fields = ['id', 'created_at']1011 def validate_email(self, value):12 if User.objects.filter(email=value).exists():13 raise serializers.ValidationError("Email already exists")14 return value
▸Вложенные сериализаторы
1class ProductSerializer(serializers.ModelSerializer):2 category_name = serializers.CharField(source='category.name', read_only=True)34 class Meta:5 model = Product6 fields = ['id', 'name', 'price', 'category', 'category_name']78class OrderSerializer(serializers.ModelSerializer):9 products = ProductSerializer(many=True, read_only=True)10 total_price = serializers.SerializerMethodField()1112 class Meta:13 model = Order14 fields = ['id', 'products', 'total_price', 'created_at']1516 def get_total_price(self, obj):17 return sum(p.price for p in obj.products.all())
ViewSets
▸ModelViewSet
1# views.py2from rest_framework import viewsets, status3from rest_framework.decorators import action4from rest_framework.response import Response5from .models import User6from .serializers import UserSerializer78class UserViewSet(viewsets.ModelViewSet):9 queryset = User.objects.all()10 serializer_class = UserSerializer1112 @action(detail=False, methods=['get'])13 def me(self, request):14 serializer = self.get_serializer(request.user)15 return Response(serializer.data)1617 @action(detail=True, methods=['post'])18 def activate(self, request, pk=None):19 user = self.get_object()20 user.is_active = True21 user.save()22 return Response({'status': 'activated'})
▸URL Configuration
1# urls.py2from django.urls import path, include3from rest_framework.routers import DefaultRouter4from .views import UserViewSet56router = DefaultRouter()7router.register(r'users', UserViewSet)89urlpatterns = [10 path('api/', include(router.urls)),11]
Аутентификация
▸Token Authentication
1# views.py2from rest_framework.authtoken.views import ObtainAuthToken3from rest_framework.authtoken.models import Token45class CustomAuthToken(ObtainAuthToken):6 def post(self, request, *args, **kwargs):7 serializer = self.serializer_class(data=request.data,8 context={'request': request})9 serializer.is_valid(raise_exception=True)10 user = serializer.validated_data['user']11 token, created = Token.objects.get_or_create(user=user)12 return Response({13 'token': token.key,14 'user_id': user.pk,15 'email': user.email16 })
▸JWT Authentication
1# settings.py2REST_FRAMEWORK = {3 'DEFAULT_AUTHENTICATION_CLASSES': (4 'rest_framework_simplejwt.authentication.JWTAuthentication',5 ),6}78# urls.py9from rest_framework_simplejwt.views import (10 TokenObtainPairView,11 TokenRefreshView,12)1314urlpatterns = [15 path('api/token/', TokenObtainPairView.as_view()),16 path('api/token/refresh/', TokenRefreshView.as_view()),17]
Разрешения (Permissions)
1from rest_framework import permissions23class IsOwnerOrReadOnly(permissions.BasePermission):4 def has_object_permission(self, request, view, obj):5 if request.method in permissions.SAFE_METHODS:6 return True7 return obj.owner == request.user89class IsAdminOrReadOnly(permissions.BasePermission):10 def has_permission(self, request, view):11 if request.method in permissions.SAFE_METHODS:12 return True13 return request.user and request.user.is_staff1415# Использование16class ArticleViewSet(viewsets.ModelViewSet):17 queryset = Article.objects.all()18 serializer_class = ArticleSerializer19 permission_classes = [IsAdminOrReadOnly]
Пагинация
1from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination23class StandardResultsSetPagination(PageNumberPagination):4 page_size = 205 page_size_query_param = 'page_size'6 max_page_size = 10078# Использование9class ArticleViewSet(viewsets.ModelViewSet):10 pagination_class = StandardResultsSetPagination
Фильтрация
1from django_filters.rest_framework import DjangoFilterBackend2from rest_framework.filters import SearchFilter, OrderingFilter34class ArticleViewSet(viewsets.ModelViewSet):5 filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]6 filterset_fields = ['category', 'author']7 search_fields = ['title', 'content']8 ordering_fields = ['created_at', 'title']
Тестирование API
1from rest_framework.test import APITestCase2from rest_framework import status34class UserAPITest(APITestCase):5 def setUp(self):6 self.user = User.objects.create_user(7 email='test@test.com',8 password='testpass123'9 )10 self.client.force_authenticate(user=self.user)1112 def test_get_users(self):13 response = self.client.get('/api/users/')14 self.assertEqual(response.status_code, status.HTTP_200_OK)1516 def test_create_user(self):17 data = {'name': 'John', 'email': 'john@test.com'}18 response = self.client.post('/api/users/', data)19 self.assertEqual(response.status_code, status.HTTP_201_CREATED)
Заключение
DRF — стандарт создания REST API в Django. Понимание сериализаторов, viewsets, аутентификации и разрешений критически важно для backend-разработки. На собеседовании спрашивают про проектирование API, обработку ошибок и безопасность.