FastAPI 和 HTMX,正确的方法。
主要特征:
- 正如人们所期望的那样,装饰器语法可以与 FastAPI 一起使用,无需在路由中使用未使用或神奇的依赖项。
- 可与任何模板引擎或服务器端渲染库一起使用,例如markyp-html或dominate.
- 内置Jinja2 模板支持(即使有多个模板文件夹)。
- 使渲染引擎能够访问修饰路由的所有依赖项。
- 如果FastAPI路由收到非 HTMX请求,默认情况下将保持正常工作,因此同一路由可以同时提供数据和渲染 HTML。
- 正确的类型可以将其他(类型化)装饰器应用到您的路由中。
- 适用于同步和异步路由。
该软件包在 PyPI 上可用,可以通过以下方式安装:
$ pip install fasthx
Jinja2 模板
要开始服务 HTMX 请求,您所需要做的就是创建一个实例fasthx.Jinja并将其用作路由上的装饰器,如下所示:
from fastapi import FastAPI from fastapi.templating import Jinja2Templates from fasthx import Jinja
# Create the app. app = FastAPI()
创建一个 FastAPI Jinja2Templates 实例,并用它来创建一个作为装饰器的 FastHX Jinja 实例。 jinja = Jinja(Jinja2Templates("templates"))
@app.get("/htmx-or-data") @jinja("user-list.html") # 使用 user-list.html 模板渲染响应。 def htmx_or_data() -> dict[str, list[dict[str, str]]]: return {"users": [{"name": "Joe"}]}
@app.get("/htmx-only") @jinja.template("user-list.html", no_data=True) # 使用 user-list.html 模板渲染响应。 def htmx_only() -> dict[str, list[dict[str, str]]]: # no_data is set to True, so this route can not serve JSON, it only responds to HTMX requests. return {"users": [{"name": "Joe"}]}
|
自定义模板
自定义模板Jinja通过允许访问渲染器函数的修饰路由的所有依赖项,提供了比内置渲染器更大的灵活性:
from typing import Annotated, Any
from fastapi import Depends, FastAPI, Request from fasthx import hx
# Create the app. app = FastAPI()
# 创建依赖项,查看其返回值是否可在呈现函数中使用。 def get_random_number() -> int: return 4 # Chosen by fair dice roll.
DependsRandomNumber = Annotated[int, Depends(get_random_number)]
# # 如果使用静态类型检查器,"result "的类型提示必须与使用该呈现方法的路由的返回类型 注释相匹配。 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("/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"}]
|
唯一依赖项是fastapi