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

В чем разница между 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 интерфейсом. Основной цикл:

  1. Запрос (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. Основной цикл:

  1. Запрос (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 предоставляет встроенные возможности для пагинации, фильтрации, поиска
В чем разница между Django и DRF? | PrepBro