Создание представлений
Функция представления, или коротко представление, — это функция 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, а также библиотеку Pythondatetime. -
Далее, мы определяем функцию под названием
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 (что означает «OK»). Полный список доступных подклассов можно найти в документации запросов/ответов. Верните экземпляр одного из этих подклассов вместо обычного 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/5.0/topics/http/views/