Usando Websocket IO, con Flask y Javascript.


Uno de los aspectos de los Sistemas Web que empezaron a masificarse, fueron las notificaciones en "tiempo real". Esto y más la necesidad de contar con la información, lo más pronto posible, hicieron que los desarrolladores crearan e implementaran herramientas para tal fin. Tal es el caso de los Web Socket, que permiten, mostrar salidas de información en el momento en que esta es procesada.
La tecnología de Sockets no es nueva. Es la base de los chats en tiempo real, desde la época de ICQ incluso. Las redes sociales como Facebook y X, las usan hace mucho tiempo, dentro de sus plataformas web. En el caso que nos compete, un WebSocket funciona de la misma manera, pero bajo un socket único con protocolo TCP, que nos permite una comunicación bidireccional y full-duplex, permitiendo poder tener información en tiempo real de cualquier actividad.
En Flask, micro framework de Python para Web, que he estado usando (y aprendiendo), hice una pequeña prueba con notificaciones toast, las cuáles, al realizar una acción que amerite una, se desplegara apenas esté ejecutada la tarea. Los pasos para implementarlo fueron los siguientes.
Instalación de WebSocket IO.
Esta se realiza tanto en el backend como en el front.
Dentro del directorio de la aplicación, se añade desde el gestor de paquetes pip, lo siguiente.
pip install flask-socketio
Esto instalará los archivos necesarios para activar el socket.
En la vista debe ir la librería socketio
, la cual llamaré con su correspondiente CDN
<script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script>
Ambas librerías son necesarias para la comunicación efectiva entre cliente-servidor.
Como he estado desarrollando una aplicación, la integré en esta de la siguiente manera. Por ejemplo. poseo un archivo Utils.py
con funciones que reutilizo dentro del código principal. Importo la librería en este.
from flask_socketio import SocketIO
# creo la instancia del web socket
socketio = SocketIO()
Con esto ya podemos implementarlo en nuestro backend.
Implementación.
Backend: Python Flask.
En el controlador, se creará una instancia que notifique.
Controlador con su correspondiente ruta.
from models import documentosModel, usuarioModel
from utils import Utils
@docu.route('/notificardocu', methods = ['POST'])
def notificar_docu():
response = {}
if request.method == 'POST':
req = request.get_json()
usuario = req.get('usuario')
empresa = req.get('empresa')
tipo = req.get('tipodocu')
idocu = req.get('id')
resp = notificar_docu_aut(usuario, empresa, tipo, idocu)
if resp == 1:
response = {'resp' : 1, 'msg' : 'Notificacion enviada exitosamente'}
else:
response = {'resp' : 0, 'msg' : 'Ocurrio un error al enviar la notificacion'}
# Logica de negocio para notificaciones automaticas.
def notificar_docu_aut(usuario, empresa, tipo, idocu):
fecha = Utils.fecha_actual()
hora = Utils.hora_actual()
tipodocumento = documentosModel.get_tipo_documento_id(tipo)
docu = documentosModel.get_detalle_docu(idocu, empresa, tipo)
titulo = f"Notificación de {str(tipodocumento[1])} N° {str(docu[0])}"
cuerpo = f'''<p>Se ha creado una {str(tipodocumento[1])} Número {Utils.lpad(str(docu[0]), 5)} </p>
<p>
<ol>
<li>Creado por: {str(session['usuario'][2])}</li>
<li>Valor Total + IVA: {str(docu[1])} </li>
</ol>
</p>
'''
estado = 'N'
resp = usuarioModel.set_notificacion(usuario, empresa, fecha, hora, titulo,cuerpo, estado)
if resp == 1:
Utils.socketio.emit('notificacion_toast', {'msg' : cuerpo})
return 1
else:
return 0
Explicación:
En este controlador tengo dos funciones. La que se comunica con la vista enviando un response y la función que crea la notificación. En esta última, si la respuesta es positiva (valor 1), invocaremos al socket implementado en Utils.socketio.emit()
con la clave 'notificacion_toast' y cuyo valor es el JSON generado con HTML para la notificación.
También debemos hacer una modificación en el archivo principal.
from flask import Flask
from utils import Utils # Incluimos la librería
from controllers import init_controllers
app = Flask(__name__, static_folder='static')
app.secret_key = 'holamundo'
init_controllers(app)
# Llamamos a socketio que será quien inicialize la aplicación
Utils.socketio.init_app(app)
if __name__ == '__main__':
Utils.socketio.run(app, debug=True)
Aquí hacemos los siguientes cambios.
Importamos la librería
Utils
para traer la instancia desocketio
Modificamos el inicializador. Para esto, usamos
Utils.socketio.init_app()
y reemplazamosapp.run
()
porUtils.socketio.run
()
. Con esto, el WebSocket queda habilitado.
Front: Javascript.
En el Javascript de la vista, creamos el toast y lo cargamos con lo que viene desde el backend.
Como a mí me gusta separar código, la función para crear el toast, lo utilizo en un archivo de funciones útiles.
// Funcion para crear HTML de notificacion toast. El parámetro es el mensaje a desplegar.
function toastNotificacion(mensaje) {
const toastContainer = document.querySelector('#toast-notif')
const toast = document.createElement('div')
toast.className = 'toast align-items-center bg-white border-0 show';
toast.ariaLive = 'assertive'
toast.ariaAtomic = true
toast.role = 'alert'
toast.innerHTML = `
<div class="toast-header">
<strong class="me-auto">Notificacion</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="d-flex">
<div class="toast-body">${mensaje}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>`
toastContainer.appendChild(toast)
setTimeout(() => {
toast.remove()
}, 5000)
}
En el archivo principal main.js
agregamos lo siguiente.
// llamamos a la instancia de socket.io.min.js
const socket = io()
// Funcion para probar si esta conectado.
socket.on('connect', () => {
console.log('Conectado')
})
// implementamos la llamada a la funcion creada y le pasamos el mensaje.
socket.on('notificacion_toast', (data) => {
toastNotificacion(data.msg)
})
El método on()
del socket, "abre" la conexión hacia el backend, recibiendo la data en JSON, la cual se entregará a la vista. Con el socket ya abierto, la notificación aparecerá a quien esté dirigida, en el mismo instante en que se ha creado dicha notificación.
El resultado lo pueden ver aquí.
Terminando.
Los Web Socket son útiles si quieres enviar información en tiempo real. Pueden hacerse desde llamados a notificaciones, como a seguimiento en tiempo real de gráficos y otras informaciones que se irán generando. Con este ejemplo básico, quise mostrar esta herramienta potente que sirve mucho para dinamizar nuestras aplicaciones web, dándoles un toque moderno, con algo que, si bien ya existía, no todos la implementan. Nos vemos en otro post.
Subscribe to my newsletter
Read articles from Hermann Pollack (hpollack95) directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
