Middlewares En Django

Fecha de publicaci贸n: 8 Septiembre 2020
Tiempo de lectura: 5 min.
Premium: False
N煤mero de visitas: 213


Habr谩 ocasiones en las cuales ser谩 necesario ejecutar ciertas acciones, ya sea antes o despu茅s de cada petici贸n, y para ello podemos apoyarnos del framework Middleware que Django nos ofrece. Es sin duda un tema muy interesante. 馃槑 Es por ello que en esta ocasi贸n me gustar铆a habl谩ramos acerca de los middlewares en Django, defini茅ramos exactamente qu茅 son, c贸mo crearlos y por supuesto, c贸mo podemos sacarles el m谩ximo provecho posible.

Bien, sin m谩s introducci贸n, pongamos manos a la obra.

Middlewares en Django

Comencemos con la pregunta obligada 驴Qu茅 es un Middleware? ver谩s, en t茅rminos simples podemos definir un Middlawere c贸mo una pieza de c贸digo la cual se ejecutar谩 antes y/o despu茅s de cada petici贸n realizada al servidor.

Lo interesante de los middlewares en Django es que estos tiene la posibilidad de modificar la petici贸n antes que esta llegue a la vista, y claro antes que el template sea renderizado. Esto nos permite, no solo agregar funcionalidad extra a las vistas, si no poder realizar diferentes validaciones sobre cada una de las peticiones al servidor, ya sea con fines de seguridad o simple debug. 馃槻

Veamos un ejemplo. Para este post crearemos un Middleware el cual nos permita conocer la direcci贸n IP del cliente, posteriormente validaremos si dicha IP se encuentra o no, dentro de una lista negra, si as铆 negaremos el servicio retornando un error 404.

Para lograr esto dividiremos el post en tres partes.

  • Introducci贸n
  • Middleware
  • Negaci贸n del servicio

En la parte introductoria crearemos y configuraremos nuestro proyecto. Si t煤 ya posee un proyecto puedes saltarte este paso.

Introducci贸n.

Lo primero que haremos ser谩 un nuevo entorno de desarrollo. Para ello utilizamos el m贸dulo venv.

python -m venv env

Una vez el entorno haya sido creado, procedemos a activarlo.

source env/bin/activate

Ahora toca el turno de instalar Django.

pip install django

Listo, procedamos a crear nuestra proyecto con su correspondiente aplicaci贸n.

$ django-admin startproject tutorial
$ cd tutorial
$ python manage.py startapp posts

Registramos nuestra aplicaci贸n en el proyecto.

INSTALLED_APPS = [
    ...,
    'posts',
]

Ahora creamos nuestra url principal. El archivo urls.py deber铆a quedar algo as铆.

...
from posts.views import index

urlpatterns = [
    path('', index, name='index'),
     ...
]

Ya para finalizar creamos nuestra vista en el archivo views.py, esto para nuestra aplicaci贸n posts.

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hola mundo desde PyWomabt.")

La vista es algo bastante sencilla, 煤nicamente retornamos un peque帽o mensaje, pero para t茅rminos pr谩cticos funcionara. 馃

Si ejecutamos el servidor y nos situamos en http://localhost:8000/ obtendremos la siguiente respuesta.

Con lo cual confirmamos que nuestro proyecto esta ejecutandose de forma correctamente.

Middleware

Ok, ya tenemos el servidor funcionando, ahora procedamos a crear nuestro primer middleware, y para ello ser谩 necesario crear el archivo middleware.py. dentro de la aplicaci贸n posts.

En dicho archivo (middleware.py) colocamos las siguientes l铆neas de c贸digo.

def ip_is_valid(get_response):

    def middleware(request):
        # C贸digo que se ejecutar谩 antes del llamado a la vista.
        print('Hola mundo desde un Middleware!!!')
        response = get_response(request)
        # C贸digo que se ejecutar谩 despu茅s del llamado a la vista.
        return response

    return middleware

En este caso nuestro middleware posee por nombre ip_is_valid, puesto que su funci贸n ser谩 validar la direcci贸n IP del cliente.

Es posible que te hayas percatado que el middleware no es m谩s que un decorador; 馃構 ya que recibe como argumento una funci贸n, posee una funci贸n anidada y retorna dicha funci贸n.

Ahora procesamos a registrar el middleware en el proyecto. Nos situamos en el archivo settings.py y modificamos el listado de middlewares.

MIDDLEWARE = [
    ...
    'post.middleware.ip_is_valid',
]

Perfecto, si realizamos todos los pasos de forma correcta al volver a realizar una petici贸n sobre http://localhost:8000/ el mensaje Hola mundo desde un Middleware!!! deber谩 imprimirse en consola.

Aqu铆 hay varios puntos a tener en cuenta.

  • 1.- Tenemos acceso a la petici贸n a trav茅s del objeto request.
  • 2.- La funci贸n get_response ser谩 la encargada de ejecutar nuestra vista. Dicha funci贸n retorna lo que la vista retorne (Muy probablemente un template 馃).
  • 3.- Mediante la funci贸n middleware seremos capaces de extender funcionalidades a nuestra vista, ya sea ejecutando c贸digo antes o despu茅s que la vista sea llamada.

Con todos estos conocimientos procedamos a obtener la direcci贸n IP.

Para no hacer tan extenso el post (y complicado) me estar茅 apoyando de la librer铆a ipware para obtener dicha direcci贸n.

Procedemos a instalarla la librer铆a.

pip install django-ipware

Una vez hecho esto, el middleware quedar铆a de la siguiente forma.

from ipware import get_client_ip

def ip_is_valid(get_response):

    def middleware(request):

        ip, is_routable = get_client_ip(request)

        print(ip)
        print(is_routable)

        return self.get_response(request)

    return middleware

Si ejecutamos y realizamos la petici贸n dal servidor, deber铆amos visualizar en consola, tanto la IP (Que en nuestro caso al encontrarnos en un ambiente de desarrollo ser谩 127.0.0.1 (Localhost) ) y as铆 mismos si la direcci贸n IP se puede enrutar p煤blicamente a Internet.

127.0.0.1
False

Negaci贸n del servicio

C贸mo estamos trabajando de forma local 驴Qu茅 te parece si baneamos las peticiones provenientes de localhost? 馃槵

from ipware import get_client_ip
from django.http import HttpResponse

BLACK_LIST = [
    '127.0.0.1'
]

def ip_is_valid(get_response):

    def middleware(request):

        ip, is_routable = get_client_ip(request)

        if ip in BLACK_LIST:
            return HttpResponse('Bad request', status=404)
        else:
            return get_response(request)

    return middleware

Para este ejemplo me apoyo de una lista negra de direcciones. Validamos sobre una sola direcci贸n (localhost), sin embargo cuanto te encuentre en producci贸n podr谩s colocar la n cantidad de direcciones beneadas. Si la direcci贸n se encuentra dentro de ella retornamos un 404 al cliente.


Ahora, quiz谩s te estes preguntando 驴Este Middleware funciona sobre todas las peticiones en el proyecto? y la respuesta es s铆. Y esto es lo interesante de los middlewares, una vez que nosotros los registramos en el proyecto, estos actuar谩n para cada petici贸n sobre cada URL; en extremo de utilidad si queremos testear o simplemente validar peticiones.

Algunos ejemplos en donde es una muy buena idea implementar un Middleware podr铆as ser: Para obtener la IP de la petici贸n, validar un Access Tokens, Obtener zonas horarias, consumir API`s, crear o consular registros, crear o leer sesiones etc ... Hay una infinidad de ejemplos para los Middlewares.

Ahora, es importante mencionar que utilizar funciones no es la 煤nica forma de crear Middlewares, no, y de hecho otra forma de hacerlo es mediante clases. Utilizando clases tendremos una mayor flexibilidad sobre exactamente que vamos a ejecutar y cu谩ndo.

Veamos un r谩pido ejemplo. Realicemos un refactor a nuestros decorador, ahora utilicemos clases.

from ipware import get_client_ip
from django.http import HttpResponse

BLACK_LIST = [
    '127.0.0.1'
]

class IPIsValid():
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        ip, is_routable = get_client_ip(request)

        if ip in BLACK_LIST:
            return HttpResponse('Bad request', status=404)
        else:
            return get_response(request)
MIDDLEWARE = [
    ...
    'post.middleware.IPIsValid',
]

Al nosotros utilizar un clase c贸mo Middleware, tendremos acceso a diferentes m茅todos con los cuales podremos ser mucho m谩s puntales en indicar cuando queremos realizar una acci贸n.

Alguno de los m茅todos son:

  • process_view
  • process_exception
  • process_template_response

De estos m茅todos ya estaremos hablando en una segunda entrega, sin embargo si t煤 deseas conocerlos ahora, te comparto un link a la Documentaci贸n oficial.

Bien, con esto estar铆amos concluyendo el post en esta ocasi贸n, en donde aprendimos exactamente qu茅 es un Middleware, c贸mo podemos crearlos y c贸mo podemos utilizarlos.

Recordemos, un Middleware no es m谩s que pieza de c贸digo que se ejecuta para cada una de las peticiones realizadas al servidor. A trav茅s de ellos seremos capaces de a帽adir funcionalidades de nuestras vistas; ya sea para condicionar o simplemente debugear. 馃悕

M谩s Tips y Ejercicios 馃悕

Adquiere una subscripci贸n PyWombat por tan solo $2 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 馃敁
Nuevo l铆mite: Incrementa tu l铆mite de ejercicios por semana. 馃殌
Contenido 煤nico: Recibe semanalmente recursos exclusivos de Python (Videos, Art铆culos y Capitulos del libro PyWombat, comienza como desarrollador Python. 馃悕

Comentarios

Para poder conocer tu opini贸n es necesario ser un usuario autenticado. Login