← Назад к вопросам
В чем разница между Django и DRF?
1.3 Junior🔥 221 комментариев
#Django#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Django vs Django REST Framework (DRF)
Django и DRF (Django REST Framework) — это не конкурирующие инструменты, а дополняющие друг друга. Django — это full-stack фреймворк, DRF — это расширение Django для работы с REST API. Разберём подробно.
Django — Web Framework
Django создан для построения веб-приложений с HTML интерфейсом. Основной цикл:
- Запрос (Request) → URL Routing → View → Template → Response (HTML)
# urls.py
from django.urls import path
from .views import UserListView, UserDetailView
urlpatterns = [
path('users/', UserListView.as_view(), name='user-list'),
path('users/<int:pk>/', UserDetailView.as_view(), name='user-detail'),
]
# views.py
from django.views.generic import ListView, DetailView
from .models import User
class UserListView(ListView):
model = User
template_name = 'users/list.html'
context_object_name = 'users'
class UserDetailView(DetailView):
model = User
template_name = 'users/detail.html'
context_object_name = 'user'
# users/list.html
<html>
<body>
{% for user in users %}
<p>{{ user.name }} — {{ user.email }}</p>
{% endfor %}
</body>
</html>
Результат: HTML страница в браузере.
Django REST Framework — REST API Framework
DRF расширяет Django для построения JSON API. Основной цикл:
- Запрос (Request) → URL Routing → View → Serializer → Response (JSON)
# urls.py
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = router.urls
# views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from .serializers import UserSerializer
from .models import User
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
# Фильтрация по query параметрам
queryset = super().get_queryset()
email = self.request.query_params.get('email')
if email:
queryset = queryset.filter(email=email)
return queryset
# serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'created_at']
read_only_fields = ['id', 'created_at']
Результат: JSON ответ для фронтенда/мобильного приложения.
{
"count": 2,
"next": null,
"previous": null,
"results": [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]
}
Сравнительная таблица
┌──────────────────────────────┬────────────────┬──────────────────┐
│ Критерий │ Django │ DRF │
├──────────────────────────────┼────────────────┼──────────────────┤
│ Назначение │ Full-stack web │ REST API │
│ Ответ │ HTML страница │ JSON данные │
│ Встроены ли views │ Да (generic) │ Нет (свои views) │
│ Встроено ли сериализирование │ Нет (шаблоны) │ Да (Serializers) │
│ CSRF защита │ Встроена │ Token/Session │
│ Аутентификация │ Cookies │ Token/JWT │
│ Валидация данных │ Form.is_valid()│ serializer.valid()│
│ Пагинация │ Вручную │ Встроена │
│ Фильтрация │ Вручную │ Встроена │
│ API документация │ Нет │ Автоматическая │
│ Тестирование │ TestCase │ APITestCase │
└──────────────────────────────┴────────────────┴──────────────────┘
Практический пример: Один проект с обоими
В реальных приложениях часто используют оба вместе:
# urls.py
from django.urls import path, include
from django.views.generic import TemplateView
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, user_profile_view
from . import api_views
router = DefaultRouter()
router.register(r'api/users', UserViewSet)
urlpatterns = [
# HTML frontend (Django)
path('', TemplateView.as_view(template_name='index.html'), name='home'),
path('profile/<int:user_id>/', user_profile_view, name='user-profile'),
# JSON API (DRF)
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls')),
]
# views.py — HTML страницы
from django.shortcuts import render
from .models import User
def user_profile_view(request, user_id):
user = User.objects.get(id=user_id)
return render(request, 'profile.html', {'user': user})
# api_views.py — JSON API endpoints
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from .serializers import UserSerializer
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
Когда использовать что
Django (без DRF) — HTML интерфейс
Используйте, если:
- Нужен веб-сайт с HTML интерфейсом
- Пользователи заходят через браузер
- Рендеринг на сервере (Server-Side Rendering)
from django.shortcuts import render
from django.views import View
from .models import Product
class ProductListView(View):
def get(self, request):
products = Product.objects.all()
return render(request, 'products.html', {'products': products})
# Результат: <html>...<product>...</html>
DRF — REST API
Используйте, если:
- Нужен API для фронтенда (React, Vue, Angular)
- Нужен API для мобильного приложения
- API для third-party интеграций
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from .serializers import ProductSerializer
class ProductListAPI(APIView):
def get(self, request):
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
# Результат: [{"id": 1, "name": "..."}]
Подробно: Валидация данных
Django Forms — для HTML форм
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['name', 'email', 'password']
def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise forms.ValidationError("Email уже зарегистрирован")
return email
# В view
def create_user(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid(): # Валидация
form.save()
return redirect('user-list')
else:
form = UserForm()
return render(request, 'create_user.html', {'form': form})
DRF Serializers — для REST API
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
def validate_email(self, value):
if User.objects.filter(email=value).exists():
raise serializers.ValidationError("Email уже зарегистрирован")
return value
def create(self, validated_data):
user = User.objects.create(**validated_data)
return user
# В view
from rest_framework.views import APIView
from rest_framework.response import Response
class CreateUserAPI(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid(): # Валидация
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
Аутентификация
Django — Cookie-based
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
@login_required # Перенаправляет на /login если не авторизован
def dashboard(request):
return render(request, 'dashboard.html', {'user': request.user})
DRF — Token/JWT
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
class UserProfileAPI(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
# request.user автоматически установлен из token
return Response({'user': request.user.username})
Фронтенд отправляет:
GET /api/profile/
Authorization: Token abc123def456
Тестирование
Django TestCase
from django.test import TestCase, Client
from .models import User
class UserTests(TestCase):
def setUp(self):
self.user = User.objects.create(name='Alice', email='alice@test.com')
def test_user_profile_page(self):
client = Client()
response = client.get(f'/profile/{self.user.id}/')
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Alice')
DRF APITestCase
from rest_framework.test import APITestCase
from rest_framework.authtoken.models import Token
from .models import User
class UserAPITests(APITestCase):
def setUp(self):
self.user = User.objects.create(name='Alice', email='alice@test.com')
self.token = Token.objects.create(user=self.user)
def test_user_api_endpoint(self):
self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.token.key}')
response = self.client.get('/api/users/')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
Архитектура: Когда использовать оба
Architecture:
┌─────────────────────────────────────┐
│ Фронтенд (React, Vue) │
└──────────────┬──────────────────────┘
│
├─── GET /api/users/ ──────┐
│ │
│ DRF API VIEW │
│ ↓ │
│ Serializer │
│ ↓ │
│ Model │
│ ↓ │
│ Database │
│ │
└──────────────────────────┘
HTML Backend:
┌──────────────┬────────────────────────┐
│ Browser │ Admin Dashboard │
└──────┬───────┴──────────┬─────────────┘
│ │
├─ GET /profile ──┐│
│ ││
│ Django View ││
│ ↓ ││
│ Template ││
│ ↓ ││
│ HTML ││
│ ││
└─────────────────┘│
│
Django Admin (автоматический)
Ключевые выводы
- Django — для веб-сайтов с HTML интерфейсом (Server-Side Rendering)
- DRF — для JSON API (для фронтенда, мобильных приложений)
- Можно использовать оба вместе — API для фронтенда + HTML для админки
- Современный подход — DRF для API + React/Vue/Angular для фронтенда
- DRF требует отдельной работы для документации, валидации, аутентификации
- DRF предоставляет встроенные возможности для пагинации, фильтрации, поиска