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