Bienvenido a nuestro sitio web, en este sitio hallarás la solucíon de lo que estabas buscando.
Middleware es un marco de enlaces al procesamiento de solicitudes / respuestas de Django. Es un sistema de “complementos” ligero y de bajo nivel para alterar globalmente la entrada o salida de Django.
Cada componente de middleware es responsable de realizar una función específica. Por ejemplo, Django incluye un componente de middleware, AuthenticationMiddleware
, que asocia a los usuarios con solicitudes mediante sesiones.
Este documento explica cómo funciona el middleware, cómo se activa el middleware y cómo escribir su propio middleware. Django se envía con un middleware integrado que puede usar desde el primer momento. Están documentados en el referencia de middleware incorporada.
Escribiendo su propio middleware
Una fábrica de middleware es un invocable que requiere get_response
invocable y devuelve un middleware. Un middleware es un invocable que toma una solicitud y devuelve una respuesta, como una vista.
Un middleware se puede escribir como una función que tiene este aspecto:
defsimple_middleware(get_response):# One-time configuration and initialization.defmiddleware(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
O se puede escribir como una clase cuyas instancias son invocables, así:
classSimpleMiddleware: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
los get_response
invocable proporcionado por Django podría ser la vista real (si este es el último middleware enumerado) o podría ser el siguiente middleware en la cadena. El middleware actual no necesita saber ni preocuparse de qué es exactamente, solo que representa lo que viene a continuación.
Lo anterior es una ligera simplificación: el get_response
invocable para el último middleware de la cadena no será la vista real, sino un método contenedor del controlador que se encarga de aplicar ver middleware, llamando a la vista con los argumentos de URL adecuados y aplicando plantilla-respuesta y excepción middleware.
El middleware puede admitir solo Python sincrónico (el predeterminado), solo Python asincrónico o ambos. Ver Soporte asincrónico para obtener detalles sobre cómo publicitar lo que apoya y saber qué tipo de solicitud está recibiendo.
El middleware puede vivir en cualquier lugar de su ruta de Python.
__init__(get_response)
Las fábricas de middleware deben aceptar get_response
argumento. También puede inicializar algún estado global para el middleware. Tenga en cuenta un par de advertencias:
- Django inicializa su middleware con solo el
get_response
argumento, por lo que no puede definir__init__()
como requiriendo cualquier otro argumento. - A diferencia del
__call__()
método que se llama una vez por solicitud,__init__()
se llama solo una vez, cuando se inicia el servidor web.
Marcar middleware como no utilizado
A veces es útil determinar en el momento del inicio si se debe utilizar una pieza de middleware. En estos casos, su middleware __init__()
el método puede elevar MiddlewareNotUsed
. Luego, Django eliminará ese middleware del proceso de middleware y registrará un mensaje de depuración en el django.request registrador cuando DEBUG
es True
.
Activando middleware
Para activar un componente de middleware, agréguelo al MIDDLEWARE
lista en la configuración de Django.
En MIDDLEWARE
, cada componente de middleware está representado por un string: la ruta completa de Python a la clase o al nombre de función de la fábrica de middleware. Por ejemplo, aquí está el valor predeterminado creado por 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',]
Una instalación de Django no requiere ningún middleware. MIDDLEWARE
puede estar vacío, si lo desea, pero se recomienda encarecidamente que al menos use CommonMiddleware
.
El orden en MIDDLEWARE
importa porque un middleware puede depender de otro middleware. Por ejemplo, AuthenticationMiddleware
almacena al usuario autenticado en la sesión; por lo tanto, debe ejecutarse después SessionMiddleware
. Ver Pedido de middleware para obtener algunos consejos comunes sobre cómo ordenar las clases de middleware de Django.
Orden y capas de middleware
Durante la fase de solicitud, antes de llamar a la vista, Django aplica el middleware en el orden en el que está definido. MIDDLEWARE
, De arriba hacia abajo.
Puede pensar en ello como una cebolla: cada clase de middleware es una “capa” que envuelve la vista, que está en el núcleo de la cebolla. Si la solicitud pasa por todas las capas de la cebolla (cada una llama get_response
para pasar la solicitud a la siguiente capa), hasta la vista en el núcleo, la respuesta luego pasará por cada capa (en orden inverso) en el camino de regreso.
Si una de las capas decide hacer un cortocircuito y devolver una respuesta sin llamar a su get_response
, ninguna de las capas de la cebolla dentro de esa capa (incluida la vista) verá la solicitud o la respuesta. La respuesta solo volverá a través de las mismas capas por las que pasó la solicitud.
Otros ganchos de middleware
Además del patrón de middleware de solicitud / respuesta básico descrito anteriormente, puede agregar otros tres métodos especiales al middleware basado en clases:
process_view()
process_view(request, view_func, view_args, view_kwargs)
request
es un HttpRequest
objeto. view_func
es la función de Python que Django está a punto de usar. (Es el objeto de función real, no el nombre de la función como un string.) view_args
es una lista de argumentos posicionales que se pasarán a la vista, y view_kwargs
es un diccionario de argumentos de palabras clave que se pasarán a la vista. Ninguno view_args
ni view_kwargs
incluir el primer argumento de vista (request
).
process_view()
se llama justo antes de que Django llame a la vista.
Debería volver None
o un HttpResponse
objeto. Si vuelve None
, Django continuará procesando esta solicitud, ejecutando cualquier otra process_view()
middleware y, a continuación, la vista adecuada. Si devuelve un HttpResponse
objeto, Django no se molestará en llamar a la vista apropiada; aplicará middleware de respuesta a eso HttpResponse
y devuelve el resultado.
Nota
Accediendo request.POST
dentro del middleware antes de que se ejecute la vista o en process_view()
evitará que cualquier vista que se ejecute después de que el middleware pueda modificar los controladores de carga para la solicitud, y normalmente debe evitarse.
los CsrfViewMiddleware
La clase puede considerarse una excepción, ya que proporciona la csrf_exempt()
y csrf_protect()
decoradores que permiten que las vistas controlen explícitamente en qué punto debe ocurrir la validación CSRF.
process_exception()
process_exception(request, exception)
request
es un HttpRequest
objeto. exception
es un Exception
objeto generado por la función de vista.
Llamadas de Django process_exception()
cuando una vista genera una excepción. process_exception()
debería volver None
o un HttpResponse
objeto. Si devuelve un HttpResponse
objeto, se aplicará la respuesta de plantilla y el middleware de respuesta y la respuesta resultante se devolverá al navegador. De lo contrario, manejo de excepciones predeterminado patadas en.
Nuevamente, el middleware se ejecuta en orden inverso durante la fase de respuesta, que incluye process_exception
. Si un middleware de excepción devuelve una respuesta, el process_exception
métodos de las clases de middleware por encima de ese middleware no se llamará en absoluto.
process_template_response()
process_template_response(request, response)
request
es un HttpRequest
objeto. response
es el TemplateResponse
objeto (o equivalente) devuelto por una vista de Django o por un middleware.
process_template_response()
se llama justo después de que la vista ha terminado de ejecutarse, si la instancia de respuesta tiene un render()
método, lo que indica que es un TemplateResponse
o equivalente.
Debe devolver un objeto de respuesta que implemente un render
método. Podría alterar lo dado response
cambiando response.template_name
y response.context_data
o podría crear y devolver un nuevo TemplateResponse
o equivalente.
No es necesario generar respuestas explícitamente; las respuestas se procesarán automáticamente una vez que se haya llamado a todo el middleware de respuesta de la plantilla.
El middleware se ejecuta en orden inverso durante la fase de respuesta, que incluye process_template_response()
.
Lidiar con las respuestas en tiempo real
diferente a HttpResponse
, StreamingHttpResponse
no tiene una content
attribute. Como resultado, el middleware ya no puede asumir que todas las respuestas tendrán un content
attribute. Si necesitan acceder al contenido, deben probar las respuestas de transmisión y ajustar su comportamiento en consecuencia:
if response.streaming: response.streaming_content = wrap_streaming_content(response.streaming_content)else: response.content = alter_content(response.content)
Nota
streaming_content
debe suponerse que es demasiado grande para guardarlo en la memoria. El middleware de respuesta puede envolverlo en un nuevo generador, pero no debe consumirlo. La envoltura se implementa normalmente de la siguiente manera:
defwrap_streaming_content(content):for chunk in content:yield alter_content(chunk)
Manejo de excepciones
Django convierte automáticamente las excepciones generadas por la vista o por el middleware en una respuesta HTTP apropiada con un código de estado de error. Ciertas excepciones se convierten en códigos de estado 4xx, mientras que una excepción desconocida se convierte en un código de estado 500.
Esta conversión tiene lugar antes y después de cada middleware (puede pensar en ella como la película delgada entre cada capa de la cebolla), de modo que cada middleware siempre puede confiar en obtener algún tipo de respuesta HTTP al llamar a su get_response
invocable. Middleware no necesita preocuparse por envolver su llamada a get_response
en un try/except
y manejar una excepción que podría haber sido provocada por un middleware posterior o la vista. Incluso si el siguiente middleware de la cadena genera un Http404
excepción, por ejemplo, su middleware no verá esa excepción; en su lugar obtendrá un HttpResponse
objeto con un status_code
de 404.
Puedes configurar DEBUG_PROPAGATE_EXCEPTIONS
para True
para omitir esta conversión y propagar las excepciones hacia arriba.
Soporte asincrónico
Nuevo en Django 3.1.
El middleware puede admitir cualquier combinación de solicitudes sincrónicas y asincrónicas. Django adaptará las solicitudes para que se ajusten a los requisitos del middleware si no puede admitir ambos, pero con una penalización de rendimiento.
De forma predeterminada, Django asume que su middleware es capaz de manejar solo solicitudes sincrónicas. Para cambiar estas suposiciones, establezca lo siguiente attributes en su función o clase de fábrica de middleware:
sync_capable
es un booleano que indica si el middleware puede manejar solicitudes sincrónicas. Predeterminado aTrue
.async_capable
es un booleano que indica si el middleware puede manejar solicitudes asincrónicas. Predeterminado aFalse
.
Si su middleware tiene ambos sync_capable = True
y async_capable = True
, luego Django le pasará la solicitud sin convertirla. En este caso, puede averiguar si su middleware recibirá solicitudes asíncronas comprobando si el get_response
objeto que se le pasa es una función de rutina, utilizando asyncio.iscoroutinefunction()
.
los django.utils.decorators
el módulo contiene sync_only_middleware()
, async_only_middleware()
, y sync_and_async_middleware()
decoradores que te permitan aplique estos indicadores a las funciones de fábrica de middleware.
El invocable devuelto debe coincidir con la naturaleza sincronizada o asincrónica del get_response
método. Si tiene un asincrónico get_response
, debe devolver una función de rutina (async def
).
process_view
, process_template_response
y process_exception
Los métodos, si se proporcionan, también deben adaptarse para que coincidan con el modo sync / async. Sin embargo, Django los adaptará individualmente según sea necesario si usted no lo hace, con una penalización de rendimiento adicional.
A continuación, se muestra un ejemplo de cómo crear una función de middleware que admita ambos:
import asyncio from django.utils.decorators import sync_and_async_middleware @sync_and_async_middlewaredefsimple_middleware(get_response):# One-time configuration and initialization goes here.if asyncio.iscoroutinefunction(get_response):asyncdefmiddleware(request):# Do something here! response =await get_response(request)return response else:defmiddleware(request):# Do something here! response = get_response(request)return response return middleware
Nota
Si declara un middleware híbrido que admite llamadas sincrónicas y asincrónicas, es posible que el tipo de llamada que reciba no coincida con la vista subyacente. Django optimizará la pila de llamadas de middleware para tener la menor cantidad posible de transiciones sincronizadas / asíncronas.
Por lo tanto, incluso si está ajustando una vista asíncrona, es posible que se le llame en modo de sincronización si hay otro middleware sincrónico entre usted y la vista.
Actualización de middleware de estilo anterior a Django 1.10
class django.utils.deprecation.MiddlewareMixin
Django proporciona django.utils.deprecation.MiddlewareMixin
para facilitar la creación de clases de middleware que sean compatibles con ambos MIDDLEWARE
y el viejo MIDDLEWARE_CLASSES
y admite solicitudes sincrónicas y asincrónicas. Todas las clases de middleware incluidas con Django son compatibles con ambas configuraciones.
El mixin proporciona una __init__()
método que requiere un get_response
argumento y lo almacena en self.get_response
.
los __call__()
método:
- Llamadas
self.process_request(request)
(si está definido). - Llamadas
self.get_response(request)
para obtener la respuesta del middleware posterior y la vista. - Llamadas
self.process_response(request, response)
(si está definido). - Devuelve la respuesta.
Si se usa con MIDDLEWARE_CLASSES
, los __call__()
el método nunca se utilizará; Llamadas de Django process_request()
y process_response()
directamente.
En la mayoría de los casos, heredar de esta combinación será suficiente para hacer que un middleware antiguo sea compatible con el nuevo sistema con suficiente compatibilidad con versiones anteriores. La nueva semántica de cortocircuito será inofensiva o incluso beneficiosa para el middleware existente. En algunos casos, una clase de middleware puede necesitar algunos cambios para adaptarse a la nueva semántica.
Estas son las diferencias de comportamiento entre el uso MIDDLEWARE
y MIDDLEWARE_CLASSES
:
- Debajo
MIDDLEWARE_CLASSES
, cada middleware siempre tendrá suprocess_response
método llamado, incluso si un middleware anterior cortocircuitó al devolver una respuesta de suprocess_request
método. DebajoMIDDLEWARE
, el middleware se comporta más como una cebolla: las capas por las que pasa una respuesta al salir son las mismas capas que vieron la solicitud al entrar. Si un middleware tiene un cortocircuito, solo ese middleware y los anteriores enMIDDLEWARE
verá la respuesta. - Debajo
MIDDLEWARE_CLASSES
,process_exception
se aplica a las excepciones generadas desde un middlewareprocess_request
método. DebajoMIDDLEWARE
,process_exception
se aplica solo a las excepciones planteadas desde la vista (o desde larender
método de unTemplateResponse
). Las excepciones generadas por un middleware se convierten en la respuesta HTTP adecuada y luego se pasan al siguiente middleware. - Debajo
MIDDLEWARE_CLASSES
, si unprocess_response
método genera una excepción, elprocess_response
Los métodos de todos los middleware anteriores se omiten y500 Internal Server Error
La respuesta HTTP siempre se devuelve (incluso si la excepción generada fue, por ejemplo, unHttp404
). DebajoMIDDLEWARE
, una excepción generada por un middleware se convertirá inmediatamente en la respuesta HTTP adecuada, y luego el siguiente middleware en línea verá esa respuesta. El middleware nunca se omite debido a que un middleware genera una excepción.
Cambiado en Django 3.1:
Se agregó soporte para solicitudes asincrónicas al MiddlewareMixin
.
Nos puedes añadir valor a nuestra información cooperando tu veteranía en las ilustraciones.