Написание представлений
Функция-представление, или для краткости представление, — это функция 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, а также библиотеку Pythondatetime. -
Затем мы определяем функцию с именем
current_datetime. Это функция-представление. Каждая функция-представление принимает объектHttpRequestв качестве первого параметра, который обычно называютrequest.Обратите внимание: имя функции-представления не имеет значения; Django не требует, чтобы она называлась каким-либо определённым образом. Здесь мы называем её
current_datetime, поскольку это имя ясно указывает на её назначение. - Представление возвращает объект
HttpResponse, содержащий сформированный ответ. Каждая функция-представление отвечает за возвращение объектаHttpResponse. (Есть исключения, но мы рассмотрим их позже.)
Часовой пояс Django
В Django есть параметр TIME_ZONE, значение которого по умолчанию — America/Chicago. Скорее всего, это не ваш часовой пояс, поэтому, возможно, вы захотите изменить его в файле настроек.
Связывание URL с представлениями
Итак, подведём итог: эта функция-представление возвращает HTML-страницу с текущими датой и временем. Чтобы отображать это представление по определённому URL, вам потребуется создать URLconf; инструкции см. в разделе Диспетчер URL.
Возвращение ошибок
Django упрощает возвращение кодов ошибок HTTP. Для ряда распространённых кодов состояния HTTP, отличных от 200 (который означает «OK»), существуют подклассы HttpResponse. Полный список доступных подклассов приведён в документации запросы и ответы. Чтобы обозначить ошибку, возвращайте экземпляр одного из этих подклассов вместо обычного объекта 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 lang="en"><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/6.0/topics/http/views/