¿Cómo modularizar una aplicación Flask usando App Factories?
Iniciar un nuevo proyecto en Flask puede ser una tarea emocionante, pero a medida que la aplicación crece, es crucial mantenerla organizada y flexible. En este sentido, aprender a implementar la técnica de App Factory es esencial para cualquier desarrollador que desee estructurar su proyecto de manera eficaz tanto para entornos de desarrollo como de producción. A continuación, te mostramos cómo implementar este patrón en tu aplicación Flask.
¿Cómo crear un directorio para la app y la función createApp?
El primer paso para estructurar tu aplicación utilizando la técnica de App Factory es crear un nuevo directorio que contenga toda la lógica de tu aplicación. Haz lo siguiente:
Crea un nuevo directorio llamado app: Este será el paquete principal de tu aplicación.
Crea un archivo __init__.py dentro de app: Este archivo inicializará el paquete.
Define la función createApp en __init__.py: Esta función será responsable de retornar la instancia de la aplicación Flask.
Aquí tienes un ejemplo básico de cómo podría verse tu archivo __init__.py:
¿Cómo configurar dependencias y ajustes de la aplicación?
Una parte crítica de la configuración de la aplicación es gestionar las dependencias y ajustes. Es recomendable separar estos aspectos creando un archivo de configuración independiente:
Crea un archivo config.py en tu paquete app.
Define las clases de configuración: Puedes establecer variables como secret_key aquí.
Por ejemplo, tu archivo config.py podría verse así:
classConfig: secret_key ='super secret'
¿Cómo mover templates y archivos estáticos?
Por defecto, Flask buscará templates y archivos estáticos en ubicaciones específicas dentro de tu estructura de directorios. Para asegurarte de que Flask puede encontrarlos, debes mover tus carpetas static y templates al directorio app:
Mueve el directorio static al directorio app.
Mueve el directorio templates al directorio app.
Esto garantiza que Flask pueda acceder a estos archivos desde su nuevo punto de entrada en createApp.
¿Cómo organizar formularios en un archivo separado?
Para mantener tu aplicación ordenada, es útil mover los formularios a un archivo separado. Aquí te mostramos cómo hacerlo:
Crea un archivo forms.py dentro de tu paquete app.
Define tus formularios en forms.py: Puedes importar los formularios necesarios desde Flask.
El formato básico para tu forms.py podría ser:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired
classLoginForm(FlaskForm): username = StringField('Username', validators=[DataRequired()]) password = PasswordField('Password', validators=[DataRequired()])
Actualiza las importaciones en tu archivo principal: Asegúrate de que cualquier lugar donde se usan los formularios ahora los importe desde forms.py.
from app.forms import LoginForm
¿Cómo asegurar que todo funcione correctamente?
Después de haber hecho todos estos cambios, es crucial verificar que tu aplicación aún funcione. Ejecuta tus pruebas y asegúrate de que todas pasen correctamente:
# Comando para correr los tests en tu aplicaciónpytest
Si todo está bien configurado, podrás ver confirmación de que las pruebas se pasan correctamente, y podrás cargar tu aplicación en el navegador para verificar visualmente su funcionamiento.
Implementar App Factories en Flask es un excelente primer paso para mantener tu proyecto organizado y adaptable a diferentes entornos. Sigue explorando y profundizando en temas como Blueprints para garantizar que tu código sea modular y sostenible a largo plazo.
Quizás, para hacer más segura la app, la información sensible como la secret key podemos leerla desde el entorno.
Primero, declararla desde la terminal como hemos estado haciendo:
exportSECRET_KEY="Super Secret"
Y luego la podemos leer desde cualquier archivo Python de la siguiente manera
import os
secret_key = os.environ['SECRET_KEY']
Incluso podemos lanzar una excepción cuando la secret key no esté declarada e informarle al usuario que debe establecer una :D
Excelente forma de aumentar la seguridad 😄
Saludos amigos en esta clase se ven muchos conceptos que se pasan por delante aqui les dejo un tutorial facil de organizacion de modulos en python:
Organizacion de modulos python
Genial
No se si es una pregunta muy basica pero no me queda del todo claro por qué se pone ese punto antes del config.
from.configimportConfig
Hola, esto no es propio de flask, básicamente es del sistema operativo.
De esta forma le indica que el archivo se encuentra en el directorio actual junto al archivo donde se esta escribiendo esa linea.
si usas la terminal, lo entederas más tarde.
por ejemplo si creas una carpeta con mkdir y luego te posicionas en ella con cd.
podrias crer otra carpeta o algún archivo y despúes indicarle con un . antes.
cd ./this_folder
Entonces flask, o el archivo init.py, necesita que le indiques esto.
Espero haber ayudado.
¡Muchas gracias!
Por que al momento de crear init.py en el la carpeta de app, ya no me corre los test y muestra el siguiente error:
Usage: flask [OPTIONS]COMMAND[ARGS]...Try'flask --help'for help.Error:No such command 'test'.
si abriste una nueva terminal asegurate de importar la variable FLASK_APP, así:
exportFLASK_APP=main.py
A mi me paso, fuen porque cuando importe Config lo hice asi:
from config importConfig
Si te fijas bien, te daras cuenta que antes del config tiene que llevar un punto, el comando quedaria asi:
from.configimportConfig.
Lo mismo me paso cuando hice la importación de forms, en el video aparece:
from app.formsimportLoginForms
Pero como el archivo forms quedo dentro de la carpeta templates dentro de app el comando queda de la siguiente forma:
from app.templates.formsimportLoginForms
El punto radica en que las rutas deben estar bien especificadas, la verdad no se como le funciono al profe, si te das cuenta en el config, con el punto inicial se le esta diciendo al sistema que la carpeta se encuentra en la misma ruta del archivo main.py
Espero te funcione.
una consulta, porque se crea una variable bootstrap a la cual se le asigna Bootstrap(app)? no entiendo que funcion cumple esa variable.
Vi tu comentario y me surgió la misma duda, por lo que fui a repasar la clase y según dijo el profesor es básicamente para inicializar la extensión de bootstrap, y una vez inicializada ya podemos acceder a todos los templates y elementos de bootstrap
Por lo que pude entender cuando damos flask run en el terminal se ejecuta el main..py y este entre muchas otras cosas importa bootstrap y lo inicializa para que cuando se llamen a las plantillas se pueda usar sin ningún problema
Intenté correr el proyecto comentando dicha variable y efectivamente me salía el problema de que no se encuentran las templates bootstrap
Que solución brindan los frameworks de python si deseo renderizar con templates que estan alojados en hosts remotos? ... o bien, distribuidos en containers docker en diferentes servidores distribuidos ???
El ejemplo de este curso es de arquitectura monolitica. Y como debemos trabajar con Flask y Jinja si deseo distribuir los templates, o bien , tener por separado un template server???
En mi opinión el curso falla en no presentar el uso real de Flask como backend, que probablemente va a ser una API que sirva datos a algún front-end en React o Vue, pero definitivamente no en Jinja. Flask se hace sumamente escalable como API sirviendo a un Front-end bien construido pero para alguien que quiera montar algo pequeño, Jinja está bien y soluciona el problema inmediato aunque de manera no tan escalable.
"renderizar con templates que están alojados en hosts remotos" he experimentado que añade más latencia, intenta con un micro servicio que sirva un un index.html personalizado en función de la url, luego este archivo index.html descargara los archivos que necesita desde un CDN, lo demás son endpoints, microservicios, apis. Un app angular, la puedes dividir en módulos, optimizar en ese sentido.
Si les sale un error como este:
O como este:
Probablemente sea porque no tenemos bien escrito el archivo config
Debe estar escrito de la siguiente forma:
classConfig:SECRET_KEY='SUPER SECRET'
ayuda con esto voy con forme a la guía del curso y los aportes de los compañeros pero al momento de terminar con esta clase todo se va al carajo me saca Not Found, The requested URL was not found
Me dice que :
Using variable 'Bootstrap' before assignment
i no funciona ..
Al hacer los cambios en la estructura, me sale el siguiente error...
assert rv is self, "Popped wrong request context. (%r instead of %r)" % (
AssertionError: wrong request context. (<RequestContext 'https://localhost/hello' [GET] of app> instead of <RequestContext 'https://localhost/' [GET] of app>)
Al localhost le coloqué https aquí, para que no lo tome como comentario con links inseguros.
Me salió el mismo error pero se solucionó al mover la carpeta de templates y static dentro de app. La descripción del error de que no encontraba los templates me salió solamente en la vista web, pero no en consola como al profe.
Ya lo he solucionado, tienes que agregar una linea de código en el archivo config.p_y
"The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again"
¿Le pasó a alguien más?
Revisa que la url esté correctamente escrita. El problema no es otro más que el servidor no se encuentra, por lo tanto debe haber un problema con la url, asegurate de escribirla bien :D
si Ami también me pasó y de ahí no he podido salir
Buenas tardes, alguien me puede por favor decir el porque de este error?:
ImportError: Start directory is not importable: 'tests'
Esta estructura creo que ya esta tomando forma, esperemos terminar con un super proyecto!
Pudo haber sido mejor explicada, pero se entiende como va evolucionando la organizacion del proyecto
Que bien así el proyecto esta as organizado
Me está saliendo un pertinaz error alrealizar los test, es el siguiente:
FAIL: test_hola_post (test_base.MainTest)
Traceback (most recent call last):
File "C: \Prueba\platzi-flask\Tests\test_base.py", line 61, in test_hola_post
AssertionError: ' /' != 'ht tp://localhost/'
/
ht tp://localhost/
He navegado hasta el cansancio por internet y no logro dar con la solución, sí alguien sabe cómo, por favor. Fíjense en la fecha de la presente pregunta, estoy usando las últimas versiones de los paquete en Python/Flask.
Si tengo archivos .js del frontend donde irían?
en este caso poderemos hacer extensiones dentro de la app?
¿porque el archivo init se llama de esa manera? ¿puede tener otro nombre?
Si puede tener otro nombre, pero le recomiendo que no, al usar como nombre de un archivo "init.py" es una forma de decirle a python que el código que contiene ese archivo se va a ejecutar si o si por eso al importar la carpeta puede acceder a las funciones contenidas en el script directamente, es decir se ejecutará de forma implícita.
from app import create_app
si decide ponerle otro nombre, debe ser explicito al momento de importarlo es decir
from app/nombre_nuevo import create_app
Manejar los módulos de esta forma es más elegante y funcional, ya que es fácil de saber rápidamente que código siempre va a ejecutar al momento de importar.
En este link puede ver una explicación más técnica: