• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Создание представлений

Функция просмотра, или для краткости view, — это функция Python, которая принимает веб-запрос и возвращает веб-ответ. Этим ответом может быть HTML-содержимое веб-страницы, перенаправление, ошибка 404, XML-документ или изображение… или что-то еще, правда. Само представление содержит любую произвольную логику, необходимую для возврата этого ответа. Этот код может находиться где угодно, пока он находится на вашем пути к Python. Других требований нет, никакой «магии», так сказать. Чтобы поместить код куда-нибудь, принято помещать представления в файл с именем views.py, расположенный в каталоге вашего проекта или приложения.

Простое представление

Вот пример простого представления, которое отображает текущую дату и время, как документ HTML:

from django.http import HttpResponse
import datetime


def current_datetime(request):
    now = datetime.datetime.now()
    html = '<html lang="en"><body>It is now %s.</body></html>' % now
    return HttpResponse(html)

Давайте проанализируем код строка за строкой:

  • Сначала мы импортировали класс HttpResponse из модуля django.http и библиотеку Python datetime.

  • Теперь определим функцию current_datetime. Это функция представления. Каждая функция представления принимает объект HttpRequest первым аргументом, который обычно называют request.

    Название функции может быть каким угодно, нет никаких конкретных правил для именования. Мы назвали функцию current_datetime.

  • Представление возвращает объект HttpResponse, который содержит сгенерированный ответ. Каждая функция представления должна возвращать объект HttpResponse. (Есть исключения, но мы расскажем об этом далее.)

Часовые пояса в Django

Django содержит настройку TIME_ZONE равную по умолчанию America/Chicago. Возможно это не там, где вы живете, вы можете изменить эту настройку в файле настройки.

Сопоставление представления с URL

Итак, напомним, функция представления возвращает HTML-страницу, которая содержит текущую дату и время. Чтобы привязать это представление к определенному URL-у, необходимо создать URLconf; подробности смотрите в разделе Менеджер URL-ов.

Возвращение ошибок

Возвращение HTTP ошибок в Django очень просто. Существует ряд подклассов HttpResponse для распространенных HTTP-состояний, отличных от 200 (что означает «OK»). Вы можете посмотреть полный список доступных подклассов в разделе о HTTP запросах и ответах. Просто верните экземпляр необходимого подкласса вместо HttpResponse. Например:

from django.http import HttpResponse, HttpResponseNotFound


def my_view(request):
    # ...
    if foo:
        return HttpResponseNotFound("<h1>Page not found</h1>")
    else:
        return HttpResponse("<h1>Page was found</h1>")

Не существует подкласса для всех HTTP-состояний, так как многие из них редко используются. Однако, как указанно в описании HttpResponse, вы можете передать код HTTP-состояния в конструктор HttpResponse. Например:

from django.http import HttpResponse


def my_view(request):
    # ...

    # Return a "created" (201) response code.
    return HttpResponse(status=201)

Так как ошибка 404 самая используемая HTTP-ошибка, существует простой способ работы с такими ошибками.

Исключение Http404

class django.http.Http404

Если вы возвращаете ошибку HttpResponseNotFound, вы должны добавить HTML содержимое страницы с ошибкой:

return HttpResponseNotFound("<h1>Page not found</h1>")

Для удобства и чтобы все страницы для ошибки 404 выглядели одинаково, Django предоставляет исключение Http404. Если вы вызываете исключение Http404 в любой момент обработки запроса, Django перехватит его и вернет стандартную страницу 404 ошибки вашего проекта вместе с 404 кодом состояния HTTP.

Пример использования:

from django.http import Http404
from django.shortcuts import render
from polls.models import Poll


def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404("Poll does not exist")
    return render(request, "polls/detail.html", {"poll": p})

Чтобы переопределить страницу, которую Django возвращает для 404 ошибки, вы можете создать HTML шаблон с названием 404.html в корне каталога с шаблонами. Этот шаблон будет использоваться, если настройка DEBUG равна False.

Если указать сообщение в исключении Http404, оно появится на 404 странице при DEBUG равном True. Используйте эти сообщения для отладки; сообщения не отображаются при отключенной отладке.

Настройка представления обрабатывающего ошибки

Представления ошибок по умолчанию в Django должны быть достаточными для большинства веб-приложений, но их можно легко переопределить, если вам нужно какое-либо собственное поведение. Укажите обработчики, как показано ниже, в вашей конфигурации URL (их установка в другом месте не будет иметь никакого эффекта).

page_not_found() переопределяется handler404:

handler404 = "mysite.views.my_custom_page_not_found_view"

server_error() переопределяется handler500:

handler500 = "mysite.views.my_custom_error_view"

permission_denied() переопределяется handler403:

handler403 = "mysite.views.my_custom_permission_denied_view"

bad_request() переопределяется handler400:

handler400 = "mysite.views.my_custom_bad_request_view"

См.также

Чтобы переопределить представление, которое обрабатывает ошибку CSRF, используйте настройку CSRF_FAILURE_VIEW.

Настройка представления обрабатывающего ошибки

Чтобы проверить реакцию пользовательского обработчика ошибок, вызовите соответствующее исключение в тестовом представлении. Например:

from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import SimpleTestCase, override_settings
from django.urls import path


def response_error_handler(request, exception=None):
    return HttpResponse("Error handler content", status=403)


def permission_denied_view(request):
    raise PermissionDenied


urlpatterns = [
    path("403/", permission_denied_view),
]

handler403 = response_error_handler


# ROOT_URLCONF must specify the module that contains handler403 = ...
@override_settings(ROOT_URLCONF=__name__)
class CustomErrorHandlerTests(SimpleTestCase):
    def test_handler_renders_template_response(self):
        response = self.client.get("/403/")
        # Make assertions on the response here. For example:
        self.assertContains(response, "Error handler content", status_code=403)

Асинхронные представления

Помимо того, что представления являются синхронными функциями, они также могут быть асинхронными («асинхронными») функциями, обычно определяемыми с использованием синтаксиса Python async def. Django автоматически обнаружит их и запустит в асинхронном контексте. Однако вам нужно будет использовать асинхронный сервер на основе ASGI, чтобы получить преимущества в производительности.

Вот пример асинхронного представления:

import datetime
from django.http import HttpResponse


async def current_datetime(request):
    now = datetime.datetime.now()
    html = '<html lang="en"><body>It is now %s.</body></html>' % now
    return HttpResponse(html)

Вы можете прочитать больше о поддержке асинхронности в Django и о том, как лучше всего использовать асинхронные представления, в Асинхронная поддержка.

Back to Top