Ir al contenido

Integraciones

Resumen de integraciones

Usa Pyzed como frontend de escritorio para FastAPI, Django, SQLAlchemy, SQLModel, httpx, Pydantic y aiosqlite, con demos que siguen el tutorial oficial de cada librería.

Pyzed es solo la interfaz: el resto de tu app es Python normal. Por eso las librerías que ya usas para backends web, bases de datos y HTTP funcionan sin cambios en una app de escritorio. Esta sección muestra cómo conectar las más comunes. Cada demo parte del tutorial oficial de la propia librería (el tutorial de SQL de FastAPI, la app de encuestas de Django, el Quick Start de SQLAlchemy, los héroes de SQLModel) y le añade una ventana de Pyzed.

Cuando un backend tiene que ejecutarse junto a la ventana, Arquitecturas explica las cuatro formas de combinarlos, con un diagrama para cada una: mismo proceso, cliente y servidor, servidor integrado y API en el proceso.

Demo Librerías Qué muestra Tutorial
fastapi_heroes FastAPI, SQLModel, httpx La API del tutorial de SQL de FastAPI y un cliente de escritorio para ella, ejecutados de tres formas: servidor aparte, servidor integrado y en el proceso. FastAPI
django_polls Django, httpx El tutorial de encuestas de Django, usado desde una ventana con el ORM en el mismo proceso o por HTTP mientras corre runserver. Django
sqlalchemy_quickstart SQLAlchemy 2.0, aiosqlite Los usuarios y direcciones del ORM Quick Start, con una Session síncrona en hilos o una AsyncSession en el loop. SQLAlchemy
sqlalchemy_contacts SQLAlchemy 2.0 20.000 filas en una tabla virtual, con búsqueda y orden en SQL desde un hilo de trabajo. SQLAlchemy
sqlmodel_heroes SQLModel El tutorial de SQLModel: equipos, héroes, filtros con where(), relaciones y un formulario validado. SQLModel
sqlmodel_inventory SQLModel, Pydantic Un solo modelo para validar el formulario y definir la tabla. SQLModel
httpx_pypi httpx, Pydantic Peticiones concurrentes que llegan a la ventana a medida que responden, convertidas en modelos. httpx
httpx_download httpx Descargas en streaming con barras de progreso y cancelación. httpx
pydantic_signup Pydantic Un formulario de registro validado por un modelo, guardado y cargado como JSON. Pydantic
aiosqlite_journal aiosqlite Una conexión SQLite async que vive en el loop de Pyzed. Otras librerías

Cada demo es un pequeño proyecto de uv. Desde su carpeta:

Windows, macOS y Linux
cd examples/integrations/sqlalchemy_contacts
uv run main.py

La primera vez, uv run crea el entorno virtual e instala las dependencias del pyproject.toml de la demo. Dentro del repositorio las demos usan tu copia de Pyzed (la tabla [tool.uv.sources]); para empezar tu propia app a partir de una, copia la carpeta y borra esas dos líneas para que pyzed-ui venga de PyPI.

Una app de Pyzed ejecuta código en tres sitios. Saber en cuál cae cada llamada a una librería es todo lo que hace falta para integrar cualquier cosa:

flowchart LR
    UI["Hilo de la UI<br/>view() · update() · callbacks"]
    Loop["Loop de asyncio (un hilo)<br/>corrutinas · generadores async"]
    Threads["Hilos de trabajo<br/>Command.perform(función)"]
    UI -- "devolver una corrutina" --> Loop
    UI -- "Command.perform(fn, then)" --> Threads
    Loop -- "resultado → update()" --> UI
    Threads -- "then(resultado)" --> UI
La librería es… Úsala con Ejemplos
async (await ...) Devuelve una corrutina o un generador async desde update, un callback u on_start. Su resultado va a update. AsyncClient de httpx, aiosqlite, ORM async de Django, AsyncSession de SQLAlchemy, websockets, redis.asyncio
bloqueante Command.perform(función, then): función corre en un hilo y then(resultado) en el hilo de la UI. Sesiones de SQLAlchemy y SQLModel, requests, pandas, archivos
un servidor Ejecútalo aparte (fastapi dev, manage.py runserver) o en un hilo daemon antes de pz.run. Mira Arquitecturas. FastAPI, Django, Starlette
un stream pz.listen(generador_async) en subscriptions(). websockets, server-sent events, pub/sub de Redis

Tres reglas lo mantienen seguro:

  1. Modifica self en el hilo de la UI. Las corrutinas y los hilos devuelven resultados; update o then los guardan. Leer self desde una corrutina está bien.
  2. No bloquees nunca el hilo de la UI. Una consulta de 50 ms congela la ventana 50 ms. Usa Command.perform o una librería async.
  3. Descarta respuestas viejas. Mientras el usuario escribe una búsqueda, los resultados pueden llegar desordenados. Envía la consulta junto con la petición y descarta las respuestas de una anterior (todas las demos lo hacen en su manejador loaded).

Todas las corrutinas comparten un loop de asyncio (pz.asyncio_loop()), así que los objetos atados a un loop, como un httpx.AsyncClient o una conexión de aiosqlite, se crean una vez y se reutilizan.

La mayoría de los backends informan de una entrada inválida con una lista de errores por campo. pz.validation_errors(error) convierte cualquiera de ellos en {campo: mensaje}, y ui.field(..., error=) muestra el mensaje bajo el título del campo, con el color de error del tema:

from pydantic import ValidationError
def save(self):
try:
item = ItemIn.model_validate(self.draft)
except ValidationError as error:
self.errors = pz.validation_errors(error)
return
...
def view(self):
return ui.field("Price", ui.input(self.draft["price"], self.set_price),
error=self.errors.get("price"))

Entiende:

  • ValidationError de Pydantic y SQLModel (los mensajes de tus ValueError pierden el prefijo Value error,),
  • el JSON de una respuesta 422 de FastAPI, {"detail": [...]}, sin la parte body/query de cada ubicación, y un {"detail": "Not found"} simple,
  • el ValidationError de Django que lanza full_clean() (los errores __all__ usan la clave "").

Los campos anidados se unen con puntos ("address.city") y los errores que no son de ningún campo usan la clave "", que las demos muestran en un ui.callout.

ui.select acepta cualquier objeto como opción y lo muestra con str(): un modelo de Django, un enum, una dataclass. on_select recibe el objeto, no su texto:

ui.select(self.authors, self.draft["author"], lambda author: self.draft.update(author=author))