Django Middleware
Este post fue migrado de un blog hecho con Wordpress. Si se ve mal, dejame un comentario y lo arreglo.
Mientras estudié el tema para hacer un experimento, traduje el 80% de la documentación oficial. La dejo aquí más algunos condimentos personales.
Middleware
Es un sub framework que permite modificaciones al sistema de procesamiento de request/response de Django. Es un sistema de plugins liviano y de bajo nivel que permite alterar globalmente las entradas y salidas de Django.
Cada componente middleware es responsable de hacer alguna función específica.
Activar componentes middleware
Para hacerlo, añadirlo a la lista MIDDLEWARE_CLASSES en la configuración de Django (settings.py). En esta lista, cada componente se representa por un string: el camino completo al nombre de la clase. Por ejemplo:
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', )
En el tratamiento de requests y la generación de responses, existen dos faces:
1) Fase Request (se llama a los métodos process_request() y process_view())
2) Fase Response (se llama a los métodos process_response() y process_exception())
En la primera, las clases son aplicadas desde la primera a la última, según el orden de la lista mencionada. En la segunda fase, se aplican en orden inverso; podemos pensarlo como una cebolla:
Una instalación de Django puede funcionar sin ningún middleware, pero esto no es recomendado.
Para escribir middleware propios
Cada componente es una clase Python, que no tiene que extender a ninguna clase en particular y debe definir uno o más de los siguientes métodos.
process_request(self, request)
request es un objeto HttpRequest. El método es llamada por cada request, antes de que Django decida que vista ejecutar.
Debe retornar None o un objeto HttpResponse. Si retorna None, Django seguirá procesando el request, ejecutando los otros middlewares y luego la vista apropiada. Si retorna un objeto HttpResponse, Django no hará nada más, solo retornar ese objeto.
process_view(self, request, view_func, view_args, view_kwargs)
request es un objeto HttpRequest. view_func es la función Python que Django está por usar. (Es el objeto function, no el nombre de la función en un string). view_args es un alista de argumentos posicionales que serán pasados a la vista. Y view_kwargs es un diccionario de argumentos de palagra clave que serán pasados a la vista. Ni view_args ni view_kwargs incluye al primer argumento de la vista (request).
process_view() es llamado antes de que Django ejecute la vista. Debe retornar None o un objeto HttpResponse. Si retorna None, Django seguirá procesando el request, ejecutando otros process_view() y luego la vista apropiada. Si retorna un objeto HttpResponse, Django no hará nada más, solo retornar ese objeto.
process_response(self, request, response)
request es un objeto HttpRequest. response es un objeto HttpResponse retornado por una vista de Django.
process_response() debe retornar un objeto HttpResponse. Puede altener el objeto response dado o puede crear uno nuevo.
A diferencia de proces_request() y process_view(), este siempre es ejecutado.
process_exception(self, request, exception)
request es un objeto HttpRequest. exception es un objeto Exception lanzado por la vista.
Django llama a process_exception() cuando la vista lanza una excepción. process_exception() debe retornar None o un objeto HttpResponse. Si retorna un objeto HttpResponse, la respuesta es devuelta al navegador. De lo contrario, el sistema por defecto para manejo de excepciones entra en acción.
__init__
Por lo general estas clases no tienen estado; simplemente contienen a los anteriores métodos. Se puede usar el método init pero se debe tener en cuenta que Django inicializa estas clases sin argumentos y que el método init es llamado solo una vez, cuando el servidor web arranca.
Experimento
Con lo anterior en mente, me quedaron algunas dudas al respecto:
- si modifico los argumentos de view_func en process_view y retorno None, ¿estos son pasados modificados a la vista?
- si lo anterior es falso, puedo lograr el mismo efecto haciendo:
def process_view(self,request, view_func, view_args, view_kwargs): # modificar request, view_args y view_kwargs return view_func(request, view_args, view_kwargs)
? - ¿puedo definir process_response de tal forma que examine response?
Comentarios
Comments powered by Disqus