Spec-Zone.ru › Django 4.2

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

Функция представления, или коротко представление, — это функция 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><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

Давайте пройдёмся по этому коду построчно:

  • Сначала мы импортируем класс HttpResponse из модуля django.http, а также библиотеку Python datetime.
  • Далее, мы определяем функцию с именем current_datetime. Это функция представления. Каждая функция представления принимает объект HttpRequest в качестве первого параметра, который обычно называется request.

    Обратите внимание, что имя функции представления не имеет значения; Django распознаёт её без каких-либо определённых требований к имени. Здесь мы называем её current_datetime, потому что это имя ясно указывает на её назначение.

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

Временная зона Django

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

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

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

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

Django предоставляет средства для возвращения кодов ошибок HTTP. Существуют подклассы HttpResponse для ряда распространённых кодов состояния HTTP, отличных от 200 (что означает «ОК»). Полный список доступных подклассов можно найти в документации запрос/ответ. Верните экземпляр одного из этих подклассов вместо обычного 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 перехватит его и вернёт стандартную страницу ошибки для вашего приложения вместе с кодом ошибки HTTP 404.

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

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})

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

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

Настройка представлений ошибок

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

Представление 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_FAILURE_VIEW для переопределения представления ошибки CSRF.

Тестирование настраиваемых представлений ошибок

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

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)

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

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

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

import datetime
from django.http import HttpResponse


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

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.2/topics/http/views/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API