Blog
Hace unas lecciones atrás aclaré que al momento de desplegar nuestra aplicación en un servidor donde distintas personas del mundo tengan acceso no era recomendable utilizar la hora local que nos permite establecer python, ya que arrojará resultados erroneos y diferentes cada vez que se ejecute el bloque de código que devuelve esa hora y obviamente eso no es bueno, vamos a abrir una consola de python importamos el módulo time y vamos a comparar lo siguiente:
from datetime import datetime # Utilizamos la hora local >>> str(datetime.now()) '2020-03-13 15:24:44.741714' # Utilizamos la hora UTC >>> str(datetime.utcnow()) '2020-03-13 19:25:06.557891' >>>
Como puedes notar, la hora local es diferente a la UTC, obviamente. Si varías personas ejecutaran esto al mismo tiempo la función datetime.now()
sería diferente para cada persona, pero la función datetime.utcnow()
sería la misma y teniendo en cuenta esto, la pregunta es ¿cuál crees que es mejor para nuestra app?, pues obviamente la segunda por lógica.
Pero de igual manera, hay un problema importante con este enfoque. Porque los usuarios que se encuentren en diferentes zonas horarias, será muy difícil determinar cuándo se realizó una publicación si ven las horas en la zona horaria UTC. Tendrían que saber de antemano que las horas están en UTC para que puedan ajustar mentalmente las horas a su propia zona horaria. Imaginemos que un usuario en la zona horaria PDT que publica algo a las 3:00 p.m, e inmediatamente ve que la publicación aparece a las 10:00 p.m hora UTC, para ser más exactos a las 22:00. Eso va a ser muy confuso. Creo que hasta tu te has confundido con esta explicación, pero no te preocupes acá en esta lección te voy a enseñar a como solucionar este problema.
Conversión de zona horaria
Esta es la solución a este problema, convertir la zona horaria del usuario que este visitando nuestra web, ¿pero como lo hacemos? la verdad es que es relativamente fácil lo haremos con una librería que posee python para Flask y con un poco de ayuda de Javascript, si no sabes Javascript no te preocupes, el código que implementaremos no es difícil de entender, pero ya te digo que si no sabes Javascript debes aprenderlo porque si quieres ser desarrollador web es importante que aprendas este lenguaje, no a un nivel master o senior pero si saber al menos manejar los elementos del DOM.
Lo que vamos a hacer es permitir la conversión UTC a la zona horaria local del cliente, usando JavaScript.
Moment.js Flask-moment
Moment.js es una pequeña biblioteca para JavaScript, y es de código abierto. Tiene como finalidad llevar la representación de fecha y hora a otro nivel, ya que proporciona todas las opciones de formato imaginables y entre otras cosas interesantes.
Vamos entonces a instalarla:
pip install flask-moment
Te aviso que debemos instalar esta librería tanto en nuestro python que está instalado en nuestro sistema operativo como en el python del entorno virtual que estamos usando para esta aplicación, una vez instalada debemos agregar el objeto de esta aplicación de manera habitual como lo hemos hecho con los demás, en nuestro archivo __init__.py:
from flask import Flask from app.settings.config import Ajustes, ConexionMail from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import LoginManager import logging from logging.handlers import SMTPHandler from flask_moment import Moment app = Flask(__name__) app.config.from_object(Ajustes) bdd = SQLAlchemy(app) migrate = Migrate(app, bdd) moment = Moment(app) login = LoginManager(app) login.login_view = 'login' login.login_message = 'Por favor inicia sesión para acceder a esta página.' from app import rutas, modelos, errores # Configurando el servidor de email para los errores en formularios if app.debug == False: if ConexionMail.MAIL_SERVER: autenticacion = None if ConexionMail.MAIL_USERNAME or ConexionMail.MAIL_PASSWORD: autenticacion = (ConexionMail.MAIL_USERNAME, ConexionMail.MAIL_PASSWORD) seguridad = None if ConexionMail.MAIL_USE_TLS: seguridad = () enviar_email = SMTPHandler( mailhost = (ConexionMail.MAIL_SERVER, ConexionMail.MAIL_PORT), fromaddr = 'no-reply@' + ConexionMail.MAIL_SERVER, toaddrs = ConexionMail.ADMINS, subject='Fallo encontrado en nuestro Blog', credentials= autenticacion, secure=seguridad ) enviar_email.setLevel(logging.ERROR) app.logger.addHandler(enviar_email)
Este es mi archivo actual __init__.py en el cual ya he agregado el objeto Moment()
, como ya tenemos dicho objeto importado ahora debemos hacer que nuestras plantillas lo carguen y para lograr que nuestras plantillas (es decir, todas las que tenemos) carguen este script de Javascript, vamos a agregarlo en la plantilla base.html ya que todas las plantillas heredan de esta y así estará disponible para todas, entonces al final de nuestro código html agregamos el siguiente código:
<script> function uniPython_lang(){ moment.lang('es', { months: 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), monthsShort: 'En._Feb._Mar_Abr._May_Jun_Jul._Ago_Sept._Oct._Nov._Dec.'.split('_'), weekdays: 'Domingo_Lunes_Martes_Miercoles_Jueves_Viernes_Sabado'.split('_'), weekdaysShort: 'Dom._Lun._Mar._Mier._Jue._Vier._Sab.'.split('_'), weekdaysMin: 'Do_Lu_Ma_Mi_Ju_Vi_Sa'.split('_') }); } $(document).ready(function(){ uniPython_lang(); }) </script> {{ moment.include_moment() }}
El código que se encuentra dentro del script es un pequeño código que he escrito para traducir el idioma de flask-moment al español, si estas elaborando todo el código de este curso en inglés no hace falta que copies ese código, solo copia el {{ moment.include_moment() }}
Muy bien, una vez que hayamos hecho esto ya podemos a realizar los pequeños cambios para manejar correctamente las fechas y las horas en nuestro servidor para cualquier parte del mundo, primero iremos a la plantilla usuarios.html y el if de la ultima sesion debe quedar de esta manera:
{% if usuario.ultima_sesion %} <p>Ultima vez activo: {{ moment(usuario.ultima_sesion).format('DD [de] MMMM [del] YYYY [a las] h:mm a') }}</p> {% endif %}
Ahora iremos a nuestra subplantilla $post.html y le agregamos la fecha de publicación (timestamp) que a lo largo del curso no lo rendericé en la plantilla. Al realizar los cambios la plantilla debe verse así:
<table class="table table-hover"> <tr> <td width="70px"> <a href="{{ url_for('perfil_usuario', username=post.autor.username) }}"> <img src="{{ post.autor.imagen_perfil(70) }}" /> </a> </td> <td> <a href="{{ url_for('perfil_usuario', username=post.autor.username) }}"> {{ post.autor.username }} </a> dijo {{ moment(post.timestamp).fromNow() }}: <br> {{ post.cuerpo }} </td> </tr> </table>
Una vez que hayamos hecho todo esto, ya tendremos solucionado este pequeño problema y nuestra aplicación ahora debería de mostrar todas las fechas de las publicaciones y de la ultima sesión del usuario de la siguiente manera:
➡ Continúa aprendiendo con nuestro Curso de Flask – Python: