Создание представлений
Функция представления, или представление вкратце, — это функция 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/4.0/topics/http/views/