Промежуточное ПО ¶
Промежуточное ПО - это структура перехватчиков для обработки запросов / ответов Django. Это легкая низкоуровневая система «плагинов» для глобального изменения ввода или вывода Django.
Каждый компонент промежуточного программного обеспечения отвечает за выполнение определенной функции. Например, Django включает компонент промежуточного программного обеспечения
AuthenticationMiddleware
, который связывает пользователей с запросами с помощью сеансов.
В этом документе объясняется, как работает промежуточное программное обеспечение, как вы активируете промежуточное программное обеспечение и как написать свое собственное промежуточное программное обеспечение. Django поставляется с некоторым встроенным промежуточным программным обеспечением, которое вы можете использовать прямо из коробки. Они задокументированы во встроенном справочнике по промежуточному программному обеспечению .
Написание собственного промежуточного программного обеспечения ¶
Фабрика промежуточного программного обеспечения - это вызываемый объект, который принимает get_response
вызываемый объект и возвращает промежуточное программное обеспечение. Промежуточное ПО - это вызываемый объект, который принимает запрос и возвращает ответ, как и представление.
Промежуточное ПО можно записать как функцию, которая выглядит так:
def simple_middleware(get_response):
# One-time configuration and initialization.
def middleware(request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
return middleware
Или его можно записать как класс, экземпляры которого вызываются, например:
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
get_response
Вызываемый при условии Джанго может быть фактическим вид (если это последний в списке промежуточного слоя) , или он может быть следующим промежуточным слоем в цепи. Текущему промежуточному программному обеспечению не нужно знать или заботиться о том, что именно оно собой представляет, просто оно представляет все, что будет дальше.
Вышеупомянутое является небольшим упрощением - get_response
вызываемый для последнего промежуточного программного обеспечения в цепочке будет не фактическим представлением, а скорее методом-оболочкой из обработчика, который заботится о применении промежуточного программного обеспечения представления , вызове представления с соответствующими аргументами URL-адреса и применении шаблона -response и
исключительное ПО промежуточного слоя .
Промежуточное ПО может поддерживать только синхронный Python (по умолчанию), только асинхронный Python или и то, и другое. См. Раздел « Асинхронная поддержка» для получения подробной информации о том, как рекламировать то, что вы поддерживаете, и о том, какой тип запроса вы получаете.
Промежуточное ПО может находиться где угодно на вашем пути Python.
__init__(get_response)
¶
Фабрики промежуточного программного обеспечения должны принимать get_response
аргумент. Вы также можете инициализировать какое-то глобальное состояние для промежуточного программного обеспечения. Имейте в виду пару предостережений:
- Django инициализирует ваше промежуточное ПО только с
get_response
аргументом, поэтому вы не можете определить,__init__()
что он требует каких-либо других аргументов. - В отличие от
__call__()
метода, который вызывается один раз для запроса, он__init__()
вызывается только один раз при запуске веб-сервера.
Пометка промежуточного ПО как неиспользуемого ¶
Иногда во время запуска полезно определить, следует ли использовать промежуточное программное обеспечение. В этих случаях __init__()
метод вашего промежуточного программного обеспечения может поднять MiddlewareNotUsed
. Затем Django удалит это промежуточное ПО из процесса промежуточного программного обеспечения и записывает отладочное сообщение в журнал django.request, когда он DEBUG
есть True
.
Активация промежуточного программного обеспечения ¶
Чтобы активировать компонент промежуточного программного обеспечения, добавьте его в MIDDLEWARE
список в настройках Django.
В MIDDLEWARE
каждый компонент промежуточного программного обеспечения представлен строкой: полный путь Python к классу или имени функции фабрики промежуточного программного обеспечения. Например, вот значение по умолчанию, созданное :django-admin
startproject
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Для установки Django не требуется никакого промежуточного программного обеспечения - MIDDLEWARE
может быть пустым, если хотите, - но настоятельно рекомендуется, чтобы вы хотя бы использовали
CommonMiddleware
.
Порядок MIDDLEWARE
имеет значение, потому что промежуточное программное обеспечение может зависеть от другого промежуточного программного обеспечения. Например,
AuthenticationMiddleware
сохраняет аутентифицированного пользователя в сеансе; следовательно, он должен работать после
SessionMiddleware
. См. Раздел
Упорядочивание промежуточного программного обеспечения для некоторых общих советов по упорядочиванию классов промежуточного программного обеспечения Django.
Порядок и наслоение промежуточного программного обеспечения ¶
На этапе запроса, перед вызовом представления, Django применяет промежуточное ПО в том порядке, в котором оно определено MIDDLEWARE
, сверху вниз.
Вы можете думать об этом как о луковице: каждый класс промежуточного программного обеспечения - это «слой», который обертывает представление, которое находится в ядре луковицы. Если запрос проходит через все уровни луковицы (каждый из них вызывает get_response
передачу запроса на следующий уровень), вплоть до представления в ядре, ответ затем пройдет через каждый уровень (в обратном порядке) на путь обратно.
Если один из уровней решает выполнить короткое замыкание и вернуть ответ, даже не вызывая его get_response
, ни один из слоев лука внутри этого слоя (включая представление) не увидит запрос или ответ. Ответ будет возвращен только через те же уровни, через которые прошел запрос.
Другие перехватчики промежуточного программного обеспечения ¶
Помимо базового шаблона промежуточного программного обеспечения запроса / ответа, описанного ранее, вы можете добавить три других специальных метода в промежуточное программное обеспечение на основе классов:
process_view()
¶
-
process_view
( запрос , view_func , view_args , view_kwargs ) ¶
request
это HttpRequest
объект. view_func
- это функция Python, которую Django собирается использовать. (Это фактический объект функции, а не имя функции в виде строки.) view_args
- это список позиционных аргументов, которые будут переданы в представление, и view_kwargs
словарь аргументов ключевых слов, которые будут переданы в представление. Ни
view_args
ни view_kwargs
включить, ни включить первый аргумент представления ( request
).
process_view()
вызывается непосредственно перед тем, как Django вызывает представление.
Он должен возвращать либо None
или HttpResponse
объект. Если он вернется None
, Django продолжит обработку этого запроса, выполняя любое другое process_view()
промежуточное программное обеспечение, а затем соответствующее представление. Если он возвращает HttpResponse
объект, Django не станет вызывать соответствующее представление; он применит к нему промежуточное ПО ответа
HttpResponse
и вернет результат.
Примечание
Доступ к request.POST
внутреннему промежуточному программному обеспечению до process_view()
запуска представления или внутри не позволит любому представлению, запущенному после промежуточного программного обеспечения, изменить обработчики загрузки для запроса , и обычно этого следует избегать.
CsrfViewMiddleware
Класс можно рассматривать как исключение, так как она обеспечивает
csrf_exempt()
и
csrf_protect()
декораторов , которые позволяют вид явно контролировать , в какой момент проверки CSRF должно произойти.
process_exception()
¶
-
process_exception
( запрос , исключение ) ¶
request
это HttpRequest
объект. exception
это
Exception
объект, созданный функцией просмотра.
Django вызывает, process_exception()
когда представление вызывает исключение.
process_exception()
должен возвращать либо None
или
HttpResponse
объект. Если он возвращает
HttpResponse
объект, будет применен ответ шаблона и промежуточное программное обеспечение ответа, и полученный ответ будет возвращен браузеру. В противном случае включается обработка исключений по умолчанию .
Опять же, промежуточное ПО запускается в обратном порядке на этапе ответа, который включает process_exception
. Если промежуточное программное обеспечение исключения возвращает ответ, process_exception
методы классов промежуточного программного обеспечения выше этого промежуточного программного обеспечения не будут вызваны вообще.
process_template_response()
¶
-
process_template_response
( запрос , ответ ) ¶
request
это HttpRequest
объект. response
- это TemplateResponse
объект (или эквивалент), возвращаемый представлением Django или промежуточным программным обеспечением.
process_template_response()
вызывается сразу после завершения выполнения представления, если у экземпляра ответа есть render()
метод, указывающий, что он является TemplateResponse
или эквивалентным.
Он должен возвращать объект ответа, реализующий render
метод. Он может изменить данное response
, изменив response.template_name
и
response.context_data
, или он может создать и вернуть совершенно новый
TemplateResponse
или эквивалентный.
Вам не нужно явно отображать ответы - ответы будут отображаться автоматически после вызова всего промежуточного программного обеспечения ответов шаблона.
Промежуточное ПО запускается в обратном порядке на этапе ответа, который включает process_template_response()
.
Работа с потоковыми ответами ¶
В отличие от HttpResponse
,
StreamingHttpResponse
не имеет content
атрибута. В результате промежуточное ПО больше не может предполагать, что все ответы будут иметь content
атрибут. Если им нужен доступ к контенту, они должны протестировать потоковые ответы и соответствующим образом скорректировать свое поведение:
if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
response.content = alter_content(response.content)
Примечание
streaming_content
следует считать, что он слишком велик для хранения в памяти. ПО промежуточного слоя ответа может обернуть его в новый генератор, но не должно его потреблять. Обертывание обычно реализуется следующим образом:
def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)
Обработка исключений ¶
Django автоматически преобразует исключения, вызванные представлением или промежуточным программным обеспечением, в соответствующий HTTP-ответ с кодом состояния ошибки. Некоторые исключения преобразуются в коды состояния 4xx, в то время как неизвестное исключение преобразуется в код состояния 500.
Это преобразование происходит до и после каждого промежуточного программного обеспечения (вы можете думать о нем как о тонкой пленке между каждым слоем луковицы), так что каждое промежуточное программное обеспечение всегда может рассчитывать на получение какого-либо ответа HTTP от вызова его get_response
вызываемого. Промежуточному программному обеспечению не нужно беспокоиться о переносе своего вызова get_response
в объект try/except
и обработке исключения, которое могло быть вызвано более поздним промежуточным программным обеспечением или представлением. Даже если следующее промежуточное ПО в цепочке вызывает
Http404
исключение, например, ваше промежуточное ПО не увидит этого исключения; вместо этого он получит HttpResponse
объект с status_code
404.
Вы можете установить, DEBUG_PROPAGATE_EXCEPTIONS
чтобы True
пропустить это преобразование и распространять исключения вверх.
Асинхронная поддержка ¶
ПО промежуточного слоя может поддерживать любую комбинацию синхронных и асинхронных запросов. Django адаптирует запросы в соответствии с требованиями промежуточного программного обеспечения, если оно не может поддерживать оба, но со снижением производительности.
По умолчанию Django предполагает, что ваше промежуточное ПО способно обрабатывать только синхронные запросы. Чтобы изменить эти предположения, установите следующие атрибуты в функции или классе фабрики промежуточного программного обеспечения:
sync_capable
- логическое значение, указывающее, может ли промежуточное ПО обрабатывать синхронные запросы. По умолчаниюTrue
.async_capable
- логическое значение, указывающее, может ли промежуточное ПО обрабатывать асинхронные запросы. По умолчаниюFalse
.
Если ваше промежуточное ПО имеет оба и
, то Django передаст ему запрос без его преобразования. В этом случае вы можете определить, будет ли ваше промежуточное ПО получать асинхронные запросы, проверив, является ли переданный вам объект функцией сопрограммы, используя .sync_capable = True
async_capable = True
get_response
asyncio.iscoroutinefunction()
django.utils.decorators
Модуль содержит
sync_only_middleware()
,
async_only_middleware()
и
sync_and_async_middleware()
декоратор , которые позволяют применять эти флаги промежуточных уровня заводских функций.
Возвращаемый вызываемый объект должен соответствовать синхронной или асинхронной природе
get_response
метода. Если у вас асинхронный get_response
, вы должны вернуть функцию сопрограммы ( ).async def
process_view
, process_template_response
и process_exception
методы, если они предусмотрены, также должны быть адаптированы для соответствия режиму синхронизации / асинхронности. Однако Django индивидуально адаптирует их по мере необходимости, если вы этого не сделаете, с дополнительным снижением производительности.
Вот пример того, как создать функцию промежуточного программного обеспечения, которая поддерживает оба:
import asyncio
from django.utils.decorators import sync_and_async_middleware
@sync_and_async_middleware
def simple_middleware(get_response):
# One-time configuration and initialization goes here.
if asyncio.iscoroutinefunction(get_response):
async def middleware(request):
# Do something here!
response = await get_response(request)
return response
else:
def middleware(request):
# Do something here!
response = get_response(request)
return response
return middleware
Примечание
Если вы объявляете гибридное промежуточное ПО, которое поддерживает как синхронные, так и асинхронные вызовы, тип получаемого вами вызова может не соответствовать базовому представлению. Django оптимизирует стек вызовов промежуточного программного обеспечения, чтобы иметь как можно меньше переходов синхронизация / асинхронность.
Таким образом, даже если вы обертываете асинхронное представление, вас могут вызвать в режиме синхронизации, если между вами и представлением есть другое синхронное промежуточное ПО.
Обновление промежуточного программного обеспечения в стиле до Django 1.10 ¶
-
класс
django.utils.deprecation.
MiddlewareMixin
¶
Django django.utils.deprecation.MiddlewareMixin
упрощает создание классов промежуточного программного обеспечения, совместимых как MIDDLEWARE
со старыми MIDDLEWARE_CLASSES
, так и со старыми , и поддерживает синхронные и асинхронные запросы. Все классы промежуточного программного обеспечения, включенные в Django, совместимы с обеими настройками.
Примесь предоставляет __init__()
метод, который требует get_response
аргумента и сохраняет его в self.get_response
.
__call__()
Метод:
- Звонки
self.process_request(request)
(если определены). - Вызывает,
self.get_response(request)
чтобы получить ответ от более позднего промежуточного программного обеспечения и представления. - Звонки (если определены).
self.process_response(request, response)
- Возвращает ответ.
Если используется с MIDDLEWARE_CLASSES
, __call__()
метод никогда не будет использоваться; Django звонит process_request()
и process_response()
напрямую.
В большинстве случаев наследования от этого миксина будет достаточно, чтобы сделать промежуточное ПО старого стиля совместимым с новой системой с достаточной обратной совместимостью. Новая семантика короткого замыкания будет безвредной или даже полезной для существующего промежуточного программного обеспечения. В некоторых случаях класс промежуточного программного обеспечения может нуждаться в некоторых изменениях, чтобы приспособиться к новой семантике.
Это поведенческие различия между использованием MIDDLEWARE
и
MIDDLEWARE_CLASSES
:
- В соответствии с этим для
MIDDLEWARE_CLASSES
каждого промежуточного программного обеспечения всегда будетprocess_response
вызываться его метод, даже если более раннее промежуточное программное обеспечение завершило работу, вернув ответ от своегоprocess_request
метода. НижеMIDDLEWARE
промежуточное ПО ведет себя больше как луковица: уровни, через которые проходит ответ на выходе, являются теми же уровнями, которые видели запрос на входе. Если промежуточное ПО замыкается, только это промежуточное ПО и те, что были до него,MIDDLEWARE
будут увидеть ответ. - Под
MIDDLEWARE_CLASSES
,process_exception
применяются для исключения поднятого из промежуточного программногоprocess_request
метода. ПодMIDDLEWARE
,process_exception
применяется только к исключениям, возникающим из представления (или изrender
метода aTemplateResponse
). Исключения, вызванные промежуточным программным обеспечением, преобразуются в соответствующий HTTP-ответ и затем передаются следующему промежуточному программному обеспечению. - Ниже
MIDDLEWARE_CLASSES
, еслиprocess_response
метод вызывает исключение,process_response
методы всего более раннего промежуточного программного обеспечения пропускаются и всегда возвращается HTTP-ответ (даже если возникшее исключение было, например, ошибкой ). Ниже исключение, вызванное промежуточным программным обеспечением, будет немедленно преобразовано в соответствующий HTTP-ответ, а затем следующее промежуточное программное обеспечение в строке увидит этот ответ. Промежуточное ПО никогда не пропускается из-за того, что промежуточное ПО вызывает исключение.500 Internal Server Error
Http404
MIDDLEWARE
Добавлена поддержка асинхронных запросов в MiddlewareMixin
.