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

Может ли Django отвечать чистым json?

2.0 Middle🔥 171 комментариев
#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Django и JSON: полный ответ

Да, Django легко может отвечать чистым JSON. В современных версиях это сделано специально для REST API.

Способ 1: JsonResponse (самый простой)

from django.http import JsonResponse

def get_users(request):
    data = {
        'users': [
            {'id': 1, 'name': 'Alice'},
            {'id': 2, 'name': 'Bob'},
        ],
        'count': 2
    }
    return JsonResponse(data)
    # Отправит: Content-Type: application/json

Отклик будет с правильным Content-Type: application/json и без дополнительного вебхлама.

Способ 2: Вручную (если нужна полная контроль)

from django.http import HttpResponse
import json

def get_data(request):
    data = {'status': 'ok', 'message': 'Hello'}
    return HttpResponse(
        json.dumps(data),
        content_type='application/json',
        status=200
    )

Способ 3: Django REST Framework (для сложных API)

from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def get_users(request):
    data = {'users': [...]}
    return Response(data)  # Автоматически JSON

DRF автоматически:

  • Сериализует данные
  • Устанавливает правильные headers
  • Обрабатывает ошибки
  • Проверяет content negotiation

Способ 4: Классовые views (DRF)

from rest_framework.views import APIView
from rest_framework.response import Response

class UserListView(APIView):
    def get(self, request):
        users = User.objects.values('id', 'name')
        return Response(list(users))

Как работает сериализация

# Проблема: datetime и другие типы не JSON-serializable
from django.utils import timezone

data = {
    'created_at': timezone.now()  # <-- ошибка!
}
return JsonResponse(data)  # TypeError

# Решение 1: default параметр
from django.core.serializers.json import DjangoJSONEncoder

return JsonResponse(
    data,
    encoder=DjangoJSONEncoder  # Знает о datetime, Decimal, UUID
)

# Решение 2: Преобразовать вручную
data = {
    'created_at': timezone.now().isoformat()  # Правильно
}

Минусы JsonResponse для больших проектов

  • Нет валидации входных данных
  • Нет документации API (Swagger/OpenAPI)
  • Нет автоматической обработки ошибок
  • Нужно вручную писать сериализаторы

Рекомендация по архитектуре

Для API используй Django REST Framework:

# urls.py
from django.urls import path
from rest_framework.routers import SimpleRouter
from .views import UserViewSet

router = SimpleRouter()
router.register(r'users', UserViewSet)

urlpatterns = router.urls  # /api/users/, /api/users/{id}/

# views.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

DRF даст тебе:

  • Сериализаторы с валидацией
  • Автоматический JSON/XML
  • Фильтрацию, пагинацию, ordering
  • Документацию через Swagger
  • Правильные HTTP статусы

Питфоллы

1. Забыли safe=False для списков:

# Ошибка!
return JsonResponse([1, 2, 3])  # Опасно

# Правильно:
return JsonResponse([1, 2, 3], safe=False)
# Или лучше:
return JsonResponse({'items': [1, 2, 3]})

2. N+1 queryset:

users = User.objects.all()  # SELECT user
data = [{'user': u, 'posts': u.posts.count()} for u in users]  # SELECT для каждого!

# Правильно:
from django.db.models import Count
users = User.objects.annotate(post_count=Count('posts'))
data = [{'user': u, 'post_count': u.post_count} for u in users]  # Одна query

Итоговый best practice

Для простых случаев: JsonResponse(data) Для API: Django REST Framework Для микросервисов: FastAPI (проще, чем Django)

Джанго прекрасно работает с JSON и не заставляет тебя писать HTML если ты не хочешь.

Может ли Django отвечать чистым json? | PrepBro