Функциональные views (FBV)

View — сердце приложения. Это функция, которая принимает request и возвращает response. С неё начинается вся логика, которую видит пользователь.
Суть: функциональная view (FBV) — это обычная Python-функция, принимающая request первым аргументом и возвращающая HttpResponse. Помощники render, redirect и get_object_or_404 упрощают типовые задачи.

Простейшая view

Функциональная view (Function-Based View, FBV) — самый прямой способ обработать запрос. Это функция, первый аргумент которой — request, а возвращает она HttpResponse:

from django.shortcuts import render, get_object_or_404, redirect
from .models import Post

def post_list(request):
    posts = Post.objects.filter(is_published=True)
    return render(request, "blog/post_list.html", {"posts": posts})

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, "blog/post_detail.html", {"post": post})

Три помощника, которые вы будете использовать постоянно

render(request, template, context) — загружает шаблон, подставляет данные из словаря context и возвращает готовый HTML-ответ. Это самый частый паттерн. get_object_or_404(Model, **kwargs) — пытается достать объект, а если его нет — отдаёт страницу 404 вместо падения с ошибкой. redirect(...) — отправляет браузер на другой URL (например, после успешной отправки формы).

Обработка GET и POST в одной view

Часто одна view обслуживает и показ формы (GET), и её обработку (POST). Тогда внутри view ветвимся по методу:

def create_post(request):
    if request.method == "POST":
        title = request.POST.get("title")
        Post.objects.create(title=title)
        return redirect("post_list")
    return render(request, "blog/create.html")

GET показывает пустую форму, POST создаёт запись и делает редирект. Паттерн «POST → redirect → GET» защищает от повторной отправки формы при обновлении страницы.

Как это работает под капотом

View — это маршрутизация плюс выбор действия по методу. По сути, это таблица «метод → функция-обработчик». Эту диспетчеризацию легко смоделировать на чистом Python — именно так Django решает, что делать с запросом:

# Попробуй сам ▶ — диспетчер методов как во view
def handle_get(data):
    return f"200 OK: показываю {len(data)} записей"

def handle_post(data):
    data.append({"title": "Новый пост"})
    return f"302 Redirect: создано, теперь {len(data)} записей"

def view(method, data):
    handlers = {"GET": handle_get, "POST": handle_post}
    handler = handlers.get(method)
    if handler is None:
        return "405 Method Not Allowed"
    return handler(data)

posts = [{"title": "Первый"}, {"title": "Второй"}]
print("GET :", view("GET", posts))
print("POST:", view("POST", posts))
print("GET :", view("GET", posts))
print("PUT :", view("PUT", posts))

Django делает ровно это: смотрит на request.method и направляет запрос в нужную ветку, а на неподдержанный метод отвечает 405.

Возврат JSON и другие типы ответов

Не все ответы — это HTML. Для API возвращают JSON через JsonResponse: return JsonResponse({"status": "ok", "count": 5}). Это основа для собственных эндпоинтов, хотя для серьёзных API используют Django REST Framework — о нём в последнем разделе. Кроме того, view может вернуть редирект (HttpResponseRedirect или удобный redirect), ошибку (HttpResponseNotFound, HttpResponseForbidden) или файл (FileResponse для отдачи документов и потоковой передачи больших файлов). Главное помнить: что бы вы ни возвращали, это всегда наследник HttpResponse с правильным кодом статуса и заголовками.

Декораторы view

Поведение view часто настраивают декораторами — обёртками, которые добавляют логику до и после вызова. Самые полезные: @require_http_methods(["GET", "POST"]) ограничивает допустимые методы (на остальные вернётся 405), @login_required закрывает страницу от анонимов, @cache_page(60) кеширует ответ на заданное время. Декораторы — чистый и переиспользуемый способ навесить общее поведение, не загромождая тело самой view проверками.

Частые ошибки

  • Забыть вернуть HttpResponse. Если функция ничего не возвращает — ошибка.
  • Не обработать отсутствие объекта. Используйте get_object_or_404, а не голый get().
  • Не делать redirect после POST. Обновление страницы повторит отправку формы.
  • Складывать всю логику в одну толстую view. Выносите её в модели и сервисы.

Best practices

  • Держите views тонкими: они оркестрируют, а не содержат бизнес-логику.
  • Всегда применяйте паттерн «POST → redirect → GET» для форм.
  • Используйте get_object_or_404 для корректных 404 вместо 500.
  • Передавайте данные в шаблон через явный словарь context.

Итоги

Функциональная view — это функция request → response. Помощники render, redirect и get_object_or_404 покрывают большинство задач. Ветвление по request.method позволяет одной view показывать и обрабатывать формы. Дальше посмотрим, как Django умеет генерировать типовые views за нас — через классы.

Проверьте себя
1. Что обязана вернуть любая view?
AСловарь
BОбъект HttpResponse (или его наследника, например render)
CСтроку
DНичего
2. Зачем после успешного POST делать redirect?
AДля красоты URL
BЧтобы обновление страницы не повторило отправку формы (POST-redirect-GET)
CЧтобы ускорить сервер
DЭто требование Python