Código fuente : https://github.com/volfpeter/fasthx
Documentación y ejemplos : https://volfpeter.github.io/fasthx
Renderización del lado del servidor Fastapi con soporte HTMX incorporado.
Características clave:
htmy , jinja2 o dominate .El paquete está disponible en PYPI y se puede instalar con:
$ pip install fasthxEl paquete tiene dependencias opcionales para las siguientes integraciones oficiales :
pip install fasthx[htmy] .pip install fasthx[jinja] . Para ejemplos completos pero simples que muestran el uso básico de FastHX , consulte la carpeta de ejemplos.
Requiere: pip install fasthx[htmy] .
Servir solicitudes HTML y HTMX con HTMY es tan fácil como crear una instancia fasthx.htmy.HTMY y usar sus métodos decoradores hx() y page() en sus rutas.
El siguiente ejemplo asume la existencia de un htmy IndexPage y un componente UserList . El ejemplo de trabajo completo con los componentes htmy se puede encontrar aquí.
from datetime import date
from fastapi import FastAPI
from pydantic import BaseModel
from fasthx . htmy import HTMY
# Pydantic model for the application
class User ( BaseModel ):
name : str
birthday : date
# Create the FastAPI application.
app = FastAPI ()
# Create the FastHX HTMY instance that renders all route results.
htmy = HTMY ()
@ app . get ( "/users" )
@ htmy . hx ( UserList ) # Render the result using the UserList component.
def get_users ( rerenders : int = 0 ) -> list [ User ]:
return [
User ( name = "John" , birthday = date ( 1940 , 10 , 9 )),
User ( name = "Paul" , birthday = date ( 1942 , 6 , 18 )),
User ( name = "George" , birthday = date ( 1943 , 2 , 25 )),
User ( name = "Ringo" , birthday = date ( 1940 , 7 , 7 )),
]
@ app . get ( "/" )
@ htmy . page ( IndexPage ) # Render the index page.
def index () -> None : ... Requiere: pip install fasthx[jinja] .
Para comenzar a servir solicitudes HTML y HTMX, todo lo que necesita hacer es crear una instancia de fasthx.Jinja y usar sus métodos hx() o page() como decoradores en sus rutas. hx() solo desencadena la representación HTML para las solicitudes HTMX, mientras que page() incondicionalmente hace que HTML. Vea el código de ejemplo a continuación:
from fastapi import FastAPI
from fastapi . templating import Jinja2Templates
from fasthx import Jinja
from pydantic import BaseModel
# Pydantic model of the data the example API is using.
class User ( BaseModel ):
first_name : str
last_name : str
# Create the app.
app = FastAPI ()
# Create a FastAPI Jinja2Templates instance and use it to create a
# FastHX Jinja instance that will serve as your decorator.
jinja = Jinja ( Jinja2Templates ( "templates" ))
@ app . get ( "/" )
@ jinja . page ( "index.html" )
def index () -> None :
...
@ app . get ( "/user-list" )
@ jinja . hx ( "user-list.html" )
async def htmx_or_data () -> list [ User ]:
return [
User ( first_name = "John" , last_name = "Lennon" ),
User ( first_name = "Paul" , last_name = "McCartney" ),
User ( first_name = "George" , last_name = "Harrison" ),
User ( first_name = "Ringo" , last_name = "Starr" ),
]
@ app . get ( "/admin-list" )
@ jinja . hx ( "user-list.html" , no_data = True )
def htmx_only () -> list [ User ]:
return [ User ( first_name = "Billy" , last_name = "Shears" )]Vea el ejemplo de trabajo completo aquí.
Requiere: pip install fasthx .
Si desea utilizar un motor de renderizado sin integración de FASTHX, puede construir fácilmente en los decoradores hx() y page() que le brindan toda la funcionalidad que necesitará. Todo lo que necesita hacer es implementar el protocolo HTMLRenderer .
De manera similar al caso Jinja, hx() solo desencadena la representación HTML para las solicitudes HTMX, mientras que page() incondicionalmente hace HTML. Vea el código de ejemplo a continuación:
from typing import Annotated , Any
from fastapi import Depends , FastAPI , Request
from fasthx import hx , page
# Create the app.
app = FastAPI ()
# Create a dependecy to see that its return value is available in the render function.
def get_random_number () -> int :
return 4 # Chosen by fair dice roll.
DependsRandomNumber = Annotated [ int , Depends ( get_random_number )]
# Create the render methods: they must always have these three arguments.
# If you're using static type checkers, the type hint of `result` must match
# the return type annotation of the route on which this render method is used.
def render_index ( result : list [ dict [ str , str ]], * , context : dict [ str , Any ], request : Request ) -> str :
return "<h1>Hello FastHX</h1>"
def render_user_list ( result : list [ dict [ str , str ]], * , context : dict [ str , Any ], request : Request ) -> str :
# The value of the `DependsRandomNumber` dependency is accessible with the same name as in the route.
random_number = context [ "random_number" ]
lucky_number = f"<h1> { random_number } </h1>"
users = "" . join (( "<ul>" , * ( f"<li> { u [ 'name' ] } </li>" for u in result ), "</ul>" ))
return f" { lucky_number } n { users } "
@ app . get ( "/" )
@ page ( render_index )
def index () -> None :
...
@ app . get ( "/htmx-or-data" )
@ hx ( render_user_list )
def htmx_or_data ( random_number : DependsRandomNumber ) -> list [ dict [ str , str ]]:
return [{ "name" : "Joe" }]
@ app . get ( "/htmx-only" )
@ hx ( render_user_list , no_data = True )
async def htmx_only ( random_number : DependsRandomNumber ) -> list [ dict [ str , str ]]:
return [{ "name" : "Joe" }]Vea el ejemplo de trabajo completo aquí.
Jinja2 con características como búsqueda activa, carga perezosa, eventos orientados al servidor, desencadenantes HTMX personalizados, diálogos y anchas de cola e integración Daisyui. La única dependencia de este paquete es fastapi .
Use ruff para pelucas y formateo, mypy para el análisis de código estático y pytest para las pruebas.
La documentación está construida con mkdocs-material y mkdocstrings .
No dude en hacer preguntas o solicitar nuevas funciones.
Y, por supuesto, todas las contribuciones son bienvenidas, que incluyen más documentación, ejemplos, código y pruebas.
El objetivo es hacer de fasthx un proyecto completo que haga que incluso sus casos de uso HTMX más complejos sean fáciles de implementar.
El paquete es de código abierto en las condiciones de la licencia MIT.
Gracias a Smart-Now por apoyar el proyecto.
![]()