HTMX + FastAPI 实战:现代化全栈开发新范式🔥 本文从零搭建一个 HTMX + FastAPI 的完整项目,带你体验"不用写一行 JavaScript"的全栈开发,涵盖动态表格、分页、表单验证、SSE 实时推送,以及4 个新手必踩的坑和解决方案。一、HTMX 是什么?为什么需要它?传统全栈开发的痛点如果你用 FastAPI 写后端,最头疼的问题是什么?# React/Vue 前端代码量 ≈ 后端代码量的 2-3 倍# 一个简单的 TODO 应用:# - FastAPI 后端:100 行# - React 前端:300 行(组件 + 状态管理 + API 调用 + loading/error 处理)# - 还要处理 CORS、打包、路由...更痛苦的是:前后端分离意味着 2 个项目、2 个部署、2 套状态管理API 类型安全:接口变了前端也不报错,运行时才发现JavaScript 疲劳:每半年一个新框架,学不动了HTMX 的解决方案HTMX 的核心思想很简单:在 HTML 中直接声明 AJAX 请求。!-- 普通链接 --ahref="/users"用户列表/a!-- HTMX:点击后 GET /users,把返回的 HTML 替换到 body 内 --buttonhx-get="/users"hx-target="#main-content"hx-swap="innerHTML"加载用户列表/buttondivid="main-content"!-- 点击按钮后,服务器返回的 HTML 片段会渲染在这里 --/div不需要:❌ 写 JavaScript fetch/axios❌ 管理前端路由❌ 处理 JSON 序列化/反序列化❌ 控制 loading/error 状态只需要:✅ 在 HTML 标签上加hx-*属性✅ 后端返回 HTML 片段(而不是 JSON)HTMX vs 主流方案对比维度HTMXReact/Vue传统 jQuery代码量最少多中等学习成本1小时2-4周1周交互体验接近 SPA原生 SPA页面刷新前后端耦合高(优势)低高类型安全天然(HTML)需 TypeScript无SEO天然支持需 SSR支持生态规模小大大适合场景内部系统/CRUD复杂 SPA旧系统维护我的观点:HTMX 不是要取代 React/Vue,而是告诉你"很多场景根本不需要前端框架"。你的管理后台、内部工具、博客系统,用 HTMX + FastAPI 可能比 SPA 方案快 2-3 倍完成。二、项目初始化2.1 环境准备# 安装 FastAPI + Jinja2 模板pipinstallfastapi uvicorn jinja2 python-multipart# 创建项目结构mkdirhtmx-fastapi-democdhtmx-fastapi-demomkdirtemplates static2.2 项目结构htmx-fastapi-demo/ ├── main.py # FastAPI 应用入口 ├── database.py # 数据库操作 ├── models.py # 数据模型 ├── templates/ │ ├── base.html # 基础模板 │ ├── index.html # 首页 │ ├── users.html # 用户列表片段 │ └── user_form.html # 用户表单片段 └── static/ └── style.css # 样式三、第一个 HTMX 应用:用户管理系统3.1 FastAPI 后端# main.pyfromfastapiimportFastAPI,Request,Form,Dependsfromfastapi.templatingimportJinja2Templatesfromfastapi.staticfilesimportStaticFilesfromfastapi.responsesimportHTMLResponseimportuvicorn app=FastAPI(title="HTMX + FastAPI Demo")app.mount("/static",StaticFiles(directory="static"),name="static")templates=Jinja2Templates(directory="templates")# 模拟数据库users_db=[{"id":1,"name":"张三","email":"zhangsan@example.com","role":"管理员"},{"id":2,"name":"李四","email":"lisi@example.com","role":"编辑"},{"id":3,"name":"王五","email":"wangwu@example.com","role":"访客"},]{# templates/base.html #} !DOCTYPE html html lang="zh-CN" head meta charset="UTF-8" meta content="width=device-width, initial-scale=1.0" script/script link title{% block title %}HTMX 示例{% endblock %}/title /head body nav hx-boost="true" {# hx-boost: 所有导航链接变成 AJAX 请求 #} a首页/a a用户管理/a /nav main {% block content %}{% endblock %} /main /body /html3.2 首页路由# main.py@app.get("/",response_class=HTMLResponse)asyncdefindex(request:Request):returntemplates.TemplateResponse("index.html",{"request":request,"message":"欢迎使用 HTMX + FastAPI!"}){# templates/index.html #} {% extends "base.html" %} {% block title %}首页{% endblock %} {% block content %} h1{ { message }}/h1 p这是一个使用 HTMX + FastAPI 构建的全栈应用演示。/p button hx-get="/users" hx-target="#user-table" hx-swap="innerHTML" 加载用户列表 /button div p点击上方按钮加载用户数据/p /div {% endblock %}3.3 用户列表(核心 HTMX 交互)# ✅ 正确:返回 HTML 片段,不是 JSON@app.get("/users",response_class=HTMLResponse)asyncdefget_users(request:Request,page:int=1):# 分页per_page=5start=(page-1)*per_page end=start+per_page page_users=users_db[start:end]total_pages=(len(users_db)+per_page-1)//per_pagereturntemplates
HTMX_FastAPI实战现代化全栈开发新范式
发布时间:2026/5/20 20:21:20
HTMX + FastAPI 实战:现代化全栈开发新范式🔥 本文从零搭建一个 HTMX + FastAPI 的完整项目,带你体验"不用写一行 JavaScript"的全栈开发,涵盖动态表格、分页、表单验证、SSE 实时推送,以及4 个新手必踩的坑和解决方案。一、HTMX 是什么?为什么需要它?传统全栈开发的痛点如果你用 FastAPI 写后端,最头疼的问题是什么?# React/Vue 前端代码量 ≈ 后端代码量的 2-3 倍# 一个简单的 TODO 应用:# - FastAPI 后端:100 行# - React 前端:300 行(组件 + 状态管理 + API 调用 + loading/error 处理)# - 还要处理 CORS、打包、路由...更痛苦的是:前后端分离意味着 2 个项目、2 个部署、2 套状态管理API 类型安全:接口变了前端也不报错,运行时才发现JavaScript 疲劳:每半年一个新框架,学不动了HTMX 的解决方案HTMX 的核心思想很简单:在 HTML 中直接声明 AJAX 请求。!-- 普通链接 --ahref="/users"用户列表/a!-- HTMX:点击后 GET /users,把返回的 HTML 替换到 body 内 --buttonhx-get="/users"hx-target="#main-content"hx-swap="innerHTML"加载用户列表/buttondivid="main-content"!-- 点击按钮后,服务器返回的 HTML 片段会渲染在这里 --/div不需要:❌ 写 JavaScript fetch/axios❌ 管理前端路由❌ 处理 JSON 序列化/反序列化❌ 控制 loading/error 状态只需要:✅ 在 HTML 标签上加hx-*属性✅ 后端返回 HTML 片段(而不是 JSON)HTMX vs 主流方案对比维度HTMXReact/Vue传统 jQuery代码量最少多中等学习成本1小时2-4周1周交互体验接近 SPA原生 SPA页面刷新前后端耦合高(优势)低高类型安全天然(HTML)需 TypeScript无SEO天然支持需 SSR支持生态规模小大大适合场景内部系统/CRUD复杂 SPA旧系统维护我的观点:HTMX 不是要取代 React/Vue,而是告诉你"很多场景根本不需要前端框架"。你的管理后台、内部工具、博客系统,用 HTMX + FastAPI 可能比 SPA 方案快 2-3 倍完成。二、项目初始化2.1 环境准备# 安装 FastAPI + Jinja2 模板pipinstallfastapi uvicorn jinja2 python-multipart# 创建项目结构mkdirhtmx-fastapi-democdhtmx-fastapi-demomkdirtemplates static2.2 项目结构htmx-fastapi-demo/ ├── main.py # FastAPI 应用入口 ├── database.py # 数据库操作 ├── models.py # 数据模型 ├── templates/ │ ├── base.html # 基础模板 │ ├── index.html # 首页 │ ├── users.html # 用户列表片段 │ └── user_form.html # 用户表单片段 └── static/ └── style.css # 样式三、第一个 HTMX 应用:用户管理系统3.1 FastAPI 后端# main.pyfromfastapiimportFastAPI,Request,Form,Dependsfromfastapi.templatingimportJinja2Templatesfromfastapi.staticfilesimportStaticFilesfromfastapi.responsesimportHTMLResponseimportuvicorn app=FastAPI(title="HTMX + FastAPI Demo")app.mount("/static",StaticFiles(directory="static"),name="static")templates=Jinja2Templates(directory="templates")# 模拟数据库users_db=[{"id":1,"name":"张三","email":"zhangsan@example.com","role":"管理员"},{"id":2,"name":"李四","email":"lisi@example.com","role":"编辑"},{"id":3,"name":"王五","email":"wangwu@example.com","role":"访客"},]{# templates/base.html #} !DOCTYPE html html lang="zh-CN" head meta charset="UTF-8" meta content="width=device-width, initial-scale=1.0" script/script link title{% block title %}HTMX 示例{% endblock %}/title /head body nav hx-boost="true" {# hx-boost: 所有导航链接变成 AJAX 请求 #} a首页/a a用户管理/a /nav main {% block content %}{% endblock %} /main /body /html3.2 首页路由# main.py@app.get("/",response_class=HTMLResponse)asyncdefindex(request:Request):returntemplates.TemplateResponse("index.html",{"request":request,"message":"欢迎使用 HTMX + FastAPI!"}){# templates/index.html #} {% extends "base.html" %} {% block title %}首页{% endblock %} {% block content %} h1{ { message }}/h1 p这是一个使用 HTMX + FastAPI 构建的全栈应用演示。/p button hx-get="/users" hx-target="#user-table" hx-swap="innerHTML" 加载用户列表 /button div p点击上方按钮加载用户数据/p /div {% endblock %}3.3 用户列表(核心 HTMX 交互)# ✅ 正确:返回 HTML 片段,不是 JSON@app.get("/users",response_class=HTMLResponse)asyncdefget_users(request:Request,page:int=1):# 分页per_page=5start=(page-1)*per_page end=start+per_page page_users=users_db[start:end]total_pages=(len(users_db)+per_page-1)//per_pagereturntemplates