Как в Django формируются HTTP-ответы?

Ответ

В Django HTTP-ответы формируются с помощью экземпляров класса HttpResponse и его подклассов. Каждый view-обработчик должен возвращать такой объект.

Основные классы для ответов:

  1. HttpResponse Базовый класс для отправки текстового контента. Используется для возврата HTML, текста, XML и т.д.

    from django.http import HttpResponse
    
    def simple_view(request):
        return HttpResponse("Это простой текстовый ответ.", content_type="text/plain")
  2. JsonResponse Специализированный подкласс для API. Автоматически сериализует Python-словари в JSON и устанавливает заголовок Content-Type: application/json.

    from django.http import JsonResponse
    
    def api_view(request):
        data = {'status': 'ok', 'data': [1, 2, 3]}
        return JsonResponse(data)
  3. HttpResponseRedirect Используется для перенаправления пользователя на другой URL. Обычно создается с помощью шортката redirect().

    from django.shortcuts import redirect
    
    def redirect_view(request):
        # Возвращает ответ с кодом 302 Found
        return redirect('/new-location/')
  4. TemplateResponse Ответ, рендеринг которого отложен. Это позволяет middleware-компонентам изменять контекст шаблона уже после того, как view его вернул, но до отправки клиенту.

    from django.template.response import TemplateResponse
    
    def template_view(request):
        context = {'user': request.user}
        return TemplateResponse(request, 'profile.html', context)

Кастомизация ответа

Любой объект ответа можно кастомизировать, изменяя его атрибуты, например, код состояния или заголовки:

response = HttpResponse("Страница не найдена", status=404)
response.headers['X-Custom-Header'] = 'MyValue'

Ответ 18+ 🔞

Давай разберём эту тему про ответы в Джанго, а то я вижу, у некоторых в голове каша, как в общественном сортире после праздника.

Смотри, вся суть в том, что любой твой вью-обработчик в Джанго должен в итоге вернуть какой-то объект ответа. Это как в магазине: ты не можешь просто взять и мысленно пожелать покупателю хорошего дня — надо рот открыть и членораздельно буркнуть. Так и здесь. Ты должен вернуть конкретную штуку.

Основные инструменты в твоём арсенале:

  1. HttpResponse — твой базовый кирпич. Это как сказать «да похуй» и выдать голый текст. HTML, XML, просто строку — что угодно.

    from django.http import HttpResponse
    
    def simple_view(request):
        return HttpResponse("Это простой текстовый ответ.", content_type="text/plain")

    Главное — не забыть указать content_type, а то браузер начнёт гадать, что это за хуйню ты ему подсунул.

  2. JsonResponse — для API, чтобы не выёбываться. Хочешь отдать JSON? Не надо вручную делать json.dumps() и ставить заголовки, ёпта. Бери готовое.

    from django.http import JsonResponse
    
    def api_view(request):
        data = {'status': 'ok', 'data': [1, 2, 3]}
        return JsonResponse(data)

    Он сам всё сериализует и заголовок application/json прилепит. Красота.

  3. HttpResponseRedirect — чтобы послать пользователя нахуй. Вернее, на другой URL. Чаще всего используется через шорткат redirect(), чтобы не париться.

    from django.shortcuts import redirect
    
    def redirect_view(request):
        # Пользователь пришёл сюда, а ты ему — а ну иди отсюда, на '/new-location/'
        return redirect('/new-location/')

    Код ответа будет 302 — «Найдено, но не здесь, иди туда».

  4. TemplateResponse — хитрая жопа с отложенным рендерингом. Это не просто рендер шаблона, а такой умный ответ, который не рендерится сразу. Зачем? Чтобы разные промежуточные слои (middleware) могли ещё долбануть по контексту или шаблону, после того как вьюшка отработала, но до того как ответ улетел к пользователю.

    from django.template.response import TemplateResponse
    
    def template_view(request):
        context = {'user': request.user}
        return TemplateResponse(request, 'profile.html', context)

    Мощная штука, но если не понимаешь зачем — не трогай, а то накосячишь.

А если хочешь настроить ответ под себя?

Да без проблем! Любой объект ответа — это же просто питонячий объект. Хочешь поменять код статуса? Пожалуйста. Хочешь прилепить свой заголовок? Да хули бы и нет.

response = HttpResponse("Страница не найдена", status=404)
response.headers['X-Custom-Header'] = 'MyValue'

Вот и всё. Главное — понимать, что ты возвращаешь, а не просто тыкать в первый попавшийся класс, как мартышка в клавиатуру.