Usando Mountaineer para desarrollar una aplicación React con Python

Mountaineer es un framework para crear aplicaciones web en Python y React fácilmente. Su idea es que el desarrollador aproveche sus conocimientos previos de Python y TypeScript para usar cada lenguaje (y framework) en la tarea que mejor se adapta a sus necesidades.
La idea básica es desarrollar el frontend como una aplicación React adecuada y el backend como varios servicios Python: todo en un solo proyecto, tipos consistentes hacia arriba y hacia abajo en la pila, enlace de datos y llamada de funciones simplificados, y renderizado del servidor para una mejor accesibilidad.
En este artículo, describiremos la configuración de un proyecto Mountaineer y mostraremos cómo desarrollar una aplicación sencilla que incluya todos los conceptos básicos. Al finalizar, podrás integrar a la perfección los componentes frontend y backend en un solo proyecto.
Configuración del entorno de desarrollo de Mountaineer
Antes de empezar, es importante configurar un entorno adecuado. Mountaineer básicamente traslada un proyecto React, que es una aplicación Node, a un entorno Python. Por lo tanto, puede ser bastante exigente con las versiones de cada componente del entorno.
Cómo analizar los paquetes de aplicaciones de Next.jsEn mi configuración, WSL ejecuta una versión bastante antigua de Ubuntu (Ubuntu 20.04.6 LTS) en Windows, por lo que tuve que actualizar los siguientes paquetes:
- Lenguaje Rust: Actualizado a la versión mayor o igual a 1.77
- Go language: Actualizado a la versión 1.22
- Nodo: Actualizado a versión mayor o igual a 20
- Lenguaje Python: Actualizado a la versión mayor o igual a 3.11
Esta configuración cambiará una vez que Mountaineer se estabilice. Cabe mencionar que el autor fue muy receptivo y me brindó apoyo cuando tuve problemas al configurar el sistema.
Una vez configurado su entorno, puede crear una aplicación repetitiva utilizando el siguiente comando:
Pipx Run Create - Alpinista - Aplicación
Esta es la función disponible para crear la estructura de directorio (bastante compleja) con todas las dependencias de los dos entornos coexistentes: el proyecto Python y el proyecto Node.
Cómo integrar WunderGraph con su aplicación frontendEn la siguiente figura se puede observar la salida del comando, que puede variar dependiendo de los requisitos preexistentes:
$ pipx ejecutar crear - montañero - aplicación? Nombre del proyecto [mi-proyecto]: microblog? Autor [ Rosario De Chiara rosdec@gmail.com ] ? ¿Usar poesía para la gestión de dependencias? [ Sí ] Sí ? ¿Crear archivos MVC de stub? [Sí] ¿No? ¿Usar Tailwind CSS? [Sí] ¿No? ¿Añadir configuración del editor? [vscode] vscode Creando proyecto... Creando. gitignore Creando docker-compose. yml Creando README. md Creando pyproject. toml Creando . env Creando microblog/aplicación. py Creando microblog/principal. py Creando microblog/cli. py Creando microblog/config. py Creando microblog/__init__. py Creando microblog/vistas/paquete. json No se detectó contenido en microblog/views/tailwind. configuración. js, omitiendo... No se detectó contenido en microblog/views/postcss. configuración. js, omitiendo... No se detectó contenido en microblog/views/__init__. py, omitiendo... No se detectó contenido en microblog/views/app/main. css, omitiendo... No se detectó contenido en microblog/views/app/home/page. tsx, omitiendo... No se detectó contenido en microblog/views/app/detail/page. tsx, saltando... No se detectó contenido en microblog/controladores/home. py , saltando... No se detectó contenido en microblog/controladores/home. microblog/controllers/detalle.py, omitiendo... Creando microblog/controllers/__ init__.py No se detectó contenido en microblog/models/detalle.py, omitiendo... Creando microblog/models/__init__.py Proyecto creado en / home/user/microblog Creando microblog virtualenv - IiOnN0qh - py3.11 es /home/user/.cache/pypoetry/virtualenvs Actualizando dependencias Resolviendo dependencias... ( 1.3s ) Operaciones de paquete : 29 instalaciones , 0 actualizaciones , 0 eliminaciones [.... INSTALACIÓN DE PAQUETES DE PYTHON ....]Escritura de archivo de bloqueoInstalando el proyecto actual : microblog ( 0.1.0 ) Poetry venv creado : /home/user/.cache/pypoetry/virtualenvs/microblog-IiOnN0qh-py3.11Se agregaron 129 paquetes y se auditaron 130 paquetes en 9 segundos. 34 paquetes buscan financiación Ejecute ` npm fund` para obtener más detalles Se encontraron 0 vulnerabilidades Entorno creado exitosamente Creando . vscode/configuración. json Configuración del editor creado en / home / usuario / microblog $
Si observa con atención, puede distinguir dos fases de instalación de dependencias. Observa cómo no solo genera el andamiaje de la aplicación, sino que también lo llena con un proyecto MVC de ejemplo.create-mountaineer-app
Para este artículo, no utilizaremos esta función, pero implementaremos una aplicación de muestra a mano con este comando:
$ poesía ejecutar servidor
Podrás iniciar el servidor web (ver http://127.0.0.1:5006/ ) y comenzar a desarrollar la aplicación con la útil recarga en caliente una vez modificado el código fuente.
Desarrollo de aplicaciones multiplataforma con Bun v1.1Debo admitir que la primera ejecución no es muy emocionante: no hay ninguna página cargada y el resultado es bastante aburrido:
Antes de comenzar el desarrollo, veamos la estructura de directorios creados por el script que acabamos de ejecutar. A partir de las descripciones, deberías poder entender dónde concentrarte según lo que pretendes hacer:
Agregar el controlador y la vista
Crear una página implica configurar un nuevo controlador para definir los datos que se pueden enviar y recibir en el frontend.
Creemos un controlador llamado en el directorio controlador; como controlador, se ejecutará en el backend y, como probablemente esperes, es un script de Python.home.py
La idea general es tener una instancia de la ControllerBase
clase e implementar el método render que proporciona la carga de datos sin procesar que se envía al frontend en la representación inicial y durante cualquier actualización de efectos secundarios.
En la mayoría de los casos, debería devolver una RenderBase
instancia (ver más abajo), pero si no tiene datos que mostrar, también puede devolver None
, como en este caso. Además, debemos configurar el url
parámetro que contiene la URL accesible al controlador y el view_path
que asocia la vista a este controlador.
La función es un componente fundamental de Mountaineer y todos los controladores deben tener una: define todos los datos que su interfaz necesitará para resolver su vista:render()
Desde la importación de montañero ControllerBase clase HomeController ( ControllerBase ): url = "/" view_path = "/app/home/page.tsx" async def render ( self ) - Ninguno : pasar
El siguiente paso es registrar el nuevo controlador en:app.py
el montañero. aplicación importante AppController de montañero. js_compiler. postcss importa PostCSSBundler de montañero. render importar LinkAttribute, Metadatos de intro_to_mountaineer. config importa AppConfig de intro_to_mountaineer. controladores. home importar HomeController controlador = AppController ( config = AppConfig (), # tipo: ignorar ) controlador .registrar ( HomeController ( ) )
En este punto, si guarda su archivo, el servidor se recargará automáticamente, registrando el nuevo controlador pero quejándose de la falta, que es la vista que hemos asociado con el nuevo controlador.page.tsx
La vista es, por supuesto, un archivo TypeScript/React:
importar React desde "react" ; importar {useServer} desde "./_server/useServer"; const Inicio = () = { const EstadoServidor = useServer (); return (div h1 Inicio / h1 p ¡Hola, mundo! / p/div); }; exportar predeterminado Inicio ;
Debes crear la ruta del directorio donde se encuentra nuestro proyecto React y colocar el archivo arriba, llamado ./app/home/
/view/
page.tsx
Si colocaste todo en los lugares correctos, tu navegador se actualizará y mostrará la página recién creada:
Si tiene un problema al colocar el archivo correcto en el directorio, verifique esta confirmación específica en el repositorio y vea cómo se ve la aplicación.
Añadiendo el modelo
Una idea inteligente de Mountaineer es que admite una base de datos PostgresSQL para respaldar tus datos. Para facilitar su uso, junto con los archivos de tu proyecto, el create_mountaineer_app
script también crea un archivo YAML para iniciar el servidor PostgresSQL en tu Docker. No tienes que encargarte de la creación de tablas; Mountaineer simplemente inspeccionará tu código en el directorio para comprender qué objetos necesitas en la base de datos.docker-compose.yml
/model
El primer paso es crear un nuevo script de Python. En este ejemplo, estará en el directorio:blogpost.py
/model
de montañista. base de datos importar SQLModel , Campo de uuid importar UUID , uuid4 de datetime importar datetime clase BlogPost ( SQLModel , tabla = True ): id : UUID = Campo ( default_factory = uuid4 , clave_principal = True ) texto : cadena de datos : str = datetime.now ( )
Para agregar este archivo al proyecto, debes incluirlo en el archivo Python:__init__.py
desde .blogpost importar BlogPost
En este punto, estamos listos para crear la tabla en la base de datos con los siguientes comandos. Por supuesto, necesita tener una docker
instalación en su sistema para instanciar el contenedor:
docker - componer - d carrera de poesía creadab
El createdb
script estará en el directorio y, para cada objeto que se haya incluido en el archivo de inicialización, creará una tabla con columnas que coincidan con los nombres y tipos definidos en el archivo (para este ejemplo)./model
__init__.py
blogpost.py
Por curiosidad, si revisas tu base de datos PostgresSQL, podrás ver la estructura de la blogpost
tabla:
Ahora tenemos todos los elementos listos para completar el desarrollo de la aplicación. Primero, agregaremos la funcionalidad para agregar una nueva entrada de blog. Para ello, debemos agregar los campos de entrada al frontend (en el directorio) y actualizar el controlador para que añada correctamente una fila a la tabla (en el directorio)./views
blogpost
/controllers
Primero agregamos un nuevo método en el backend, que es el controlador, en el archivo (el archivo completo está en el repositorio):/controllers/home.py
clase HomeController(ControllerBase): url = "/" view_path = "/app/home/page.tsx" async def render(self) - Ninguno: aprobar @sideeffect async def add_blogpost(self, payload: str, session: AsyncSession = Depends(DatabaseDependencies.get_db_session)) - Ninguno: new_blogpost = BlogPost(text = payload) session.add(new_blogpost) await session.commit()
En el código anterior, definimos el método add_blogpost
marcado por el @sideeffect
decorador. Esto le indica a Mountaineer que este código tendrá un impacto en los datos y, por lo tanto, al invocarlo, se debe recargar el estado del servidor.
El add_blogpost
método simplemente ingresará el parámetro payload, que contendrá todos los datos transferidos desde el backend y la sesión que contiene el puntero a la base de datos. Al usar el payload, creamos una nueva BlogPost
instancia de objeto, inicializándola con la cadena de payload. El new_blogpost
objeto se añade a la sesión, lo que se traduce en una inserción en la tabla Blogpost de la base de datos.
La segunda modificación se encuentra en la vista. A continuación, se muestra un fragmento del archivo (el archivo completo está en el repositorio):page.tsx
/views/app/home
const CreatePost = ({ serverState }: { serverState : ServerState }) = { const [ newBlogpost , setNewBlogpost ] = useState ( "" ); return ( div tipo de entrada = "texto" valor ={ newBlogpost } onChange ={( e ) = setNewBlogpost ( e . target . value )} / botón onClick ={ async () = { await serverState.add_blogpost ({ payload : newBlogpost.toString () }); setNewBlogpost ( " " ) ; } } Publicación/botón /div );};
En el frontend, definimos un nuevo componente de React que es simplemente un formulario simple para gestionar el cuadro de texto y el onClick
evento al enviarlo. Como se puede ver en el código anterior, simplemente invocamos el servicio de backend add_blogpost
definido en el controlador.
En la siguiente imagen, puedes ver el verdadero superpoder de Mountaineer: la fuerte interconexión entre el proyecto Python y el proyecto React/TypeScript:
En la sección de React/TypeScript del bloque de código anterior, vemos la nueva función, add_blogpost()
, añadida al controlador sin necesidad de configuración adicional. Cada vez que modificamos el código fuente, Mountaineer incorpora las modificaciones actualizando las sugerencias de tipo y de función.
Una vez que completes todas las modificaciones en el navegador, podrás ver la nueva interfaz de usuario:
Al interactuar con el formulario consultando la base de datos podrás ver que todo el proceso funciona:
Ahora tenemos un flujo de datos adecuado desde el frontend hasta la base de datos a través del backend. El último paso es implementar el flujo en sentido inverso, de la base de datos al frontend. Esto implicará cambios en dos puntos: el controlador y la vista.
El controlador tendrá una nueva versión de la render
función:
async def render(self, request: Solicitud, session: AsyncSession = Depends(DatabaseDependencies.get_db_session) ) - HomeRender: posts = await session.execute(select(BlogPost)) return HomeRender(posts=posts.scalars().all() )
render
Se invoca durante el renderizado inicial y en cualquier sideeffect
actualización. Su propósito es proporcionar los datos de la base de datos que se enviarán al frontend. Las actualizaciones se actualizan en el estado del servidor mediante la RenderBase
instancia. En el ejemplo anterior, se puede ver cómo se llena la matriz `name` posts
al ejecutar una consulta en el objeto específico BlogPost
.
En la vista, solo tenemos que manipular los datos serverState
y ensamblarlos en la interfaz: para este propósito, escribimos un nuevo componente React llamado ShowPosts
:
const ShowPosts = ({ serverState }: { serverState: ServerState }) = { return ( serverState.posts.map((post) = ( div key={post.id} div{post.text}/div div{post.data}/div br/br /div )))}
Ya sabemos que en el serverState
objeto, encontraremos un objeto llamado posts
que se rellena en el controlador anterior. Los archivos actualizados están en el repositorio y el resultado final es el siguiente:
Conclusión
Este proyecto tiene algunas similitudes con proyectos como ReactPy y PyReact. Sin embargo, a diferencia de estos, permite integrar tanto el frontend escrito en TypSscript/React puro como el backend en Python/Uvicorn puro en una única condebase, logrando un fuerte acoplamiento entre ambas capas mediante Mountaineer.
Empieza ahora
Si quieres conocer otros artículos parecidos a Usando Mountaineer para desarrollar una aplicación React con Python puedes visitar la categoría Aplicaciones.
Entradas Relacionadas