news 2026/7/6 8:18:05

FastHTML:Python原生HTML优先的极简Web框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastHTML:Python原生HTML优先的极简Web框架

1. 这不是又一个Web框架教程——FastHTML到底在解决什么问题?

你打开Python生态的Web开发地图,会看到一条清晰的“进化链”:从原始的cgi脚本,到Flask的轻量灵活,再到Django的全栈厚重,接着是Starlette/FastAPI掀起的异步+Pydantic数据验证风暴。但这条链上始终缺一块拼图——能让前端初学者不写JavaScript、不配Webpack、不学React/Vue,却能用纯HTML+少量Python逻辑,5分钟跑出可交互、带数据库、有状态的完整Web应用。FastHTML就是这块拼图。它不是要取代FastAPI,也不是要挑战Django,而是把“写个待办清单”“做个内部工具页”“搭个数据录入表单”这类高频小需求,从“需要开三个终端、装五个包、配路由+模板+静态文件+数据库迁移”的复杂流程,压缩成“一个.py文件、两段函数、三行命令”的极简体验。我第一次用它给市场部同事做客户反馈收集页,从接到需求到发链接过去,只用了22分钟——其中15分钟在等同事填完测试数据。核心关键词就三个:Python原生、HTML优先、零前端构建。它适合谁?刚学完print("Hello World")想立刻做出网页的大学生;被npm install卡住一小时、只想让Excel数据变网页的财务人员;还有像我这样,每周要临时搭3~4个内部管理页、但实在不想再为每个页面重配一遍nginx反向代理的后端老鸟。它不承诺“企业级高并发”,但绝对兑现“今天下午三点前上线”。

2. FastHTML的设计哲学与底层逻辑拆解

2.1 为什么放弃“前后端分离”范式?直击真实痛点

FastHTML的底层设计选择,源于对现实开发场景的冷峻观察。我们拆解一个典型“失败案例”:某团队用React+FastAPI做内部审批系统,前端工程师花3天搭好UI框架,后端工程师花2天写好API,联调时发现——审批状态更新需要实时推送,于是加了WebSocket;用户上传附件要预览,于是加了文件服务;权限控制要细粒度,于是加了JWT中间件……最终,一个5人日的小需求,膨胀成15人日的项目,部署要维护3个服务进程。FastHTML反其道而行之:它把HTTP请求响应周期拉长,让一次请求不仅能返回HTML,还能携带状态变更、DOM操作指令、甚至客户端JS执行逻辑。这听起来像复古的PHP时代?不,它是用现代Python机制重构了这个过程。关键在于@rt装饰器——它不是简单的路由注册,而是一个状态感知的响应生成器。当你写@rt("/"),FastHTML不仅绑定URL路径,还自动注入当前会话的session对象、内置的database连接池、甚至预编译的Jinja2模板引擎(可选)。更关键的是,它默认启用HTMX——这个库让HTML元素自带AJAX能力,比如一个<button hx-post="/delete/123">删除</button>,点击后自动发起POST请求,并把响应内容直接替换到指定DOM节点,全程无需一行JavaScript。我实测过,一个带增删改查的图书管理页,传统方案需写87行JS代码处理表单提交、错误提示、列表刷新;FastHTML版本里,JS代码为0,所有交互逻辑藏在HTML属性和Python函数里。

2.2 核心架构:三层抽象如何降低认知负荷

FastHTML的架构像一个精心设计的漏斗,把复杂性层层过滤:

  • 第一层:HTML即API
    所有交互入口都是标准HTML标签。<form>提交触发Python函数,<a>跳转加载新页面,<div hx-get="/data">异步获取内容。这意味着你不需要理解“RESTful资源设计”,只需按语义写标签。例如,要实现搜索功能,传统方案要定义GET /api/search?q=xxx端点,前端用fetch()调用;FastHTML里,直接写<input name="q" hx-get="/search" hx-trigger="keyup changed delay:500ms">,输入框内容变化500毫秒后自动发起GET请求,结果插入到指定容器。这里没有“API文档”,只有HTML规范。

  • 第二层:Python函数即渲染器
    @rt装饰的函数接收Request对象(含表单数据、查询参数、cookies),返回值直接成为HTTP响应体。但关键差异在于:返回值可以是字符串、字典、甚至自定义类实例。FastHTML内置了一套HTMLResponse类,当函数返回Div("Hello", cls="text-red-500")时,它自动序列化为<div class="text-red-500">Hello</div>;返回{"message": "success"}时,自动转为JSON响应。这种“类型即协议”的设计,让开发者不用纠结“该返回HTML还是JSON”,函数逻辑只关注业务,序列化由框架智能判断。

  • 第三层:状态管理即Python变量
    FastHTML内置了轻量级会话管理(基于签名cookies)和内存数据库(SQLite in-memory mode)。最惊艳的是state模块——它允许你在函数间共享状态,且自动处理并发安全。比如,一个计数器页面:

    from fasthtml.common import * app, rt = fast_app() count = state(0) # 全局状态变量 @rt("/") def get(): return Titled("计数器", P(f"当前计数: {count.value}"), Button("加1", hx_post="/inc"), Button("清零", hx_post="/reset")) @rt("/inc") def post(): count.value += 1 return P(f"当前计数: {count.value}")

    这里count.value的读写是线程安全的,无需threading.Lock。原理是FastHTML在每次请求前快照状态,在响应后原子更新,避免了传统Web框架中“全局变量脏读”的经典陷阱。

2.3 与同类框架的本质差异:不是“更轻”,而是“换赛道”

很多人第一反应是:“这不就是Flask+HTMX?” 我们用一张表对比本质差异:

维度Flask+HTMXFastAPI+HTMXFastHTML
路由定义@app.route("/")手动绑定@app.get("/")强类型声明@rt("/")隐式推导(自动识别HTTP方法)
数据解析request.form.get("name")手动取值Pydantic模型校验(需定义Schema)自动解析:def post(name:str, age:int)参数即校验规则
响应生成return render_template("page.html", data=data)return JSONResponse(content={"msg":"ok"})return Div(P("Hello"), H1(data.name))(HTML组件树)
状态管理依赖flask-session或手动存Redis无内置方案,需自行集成内置state()sessiondatabase三态统一接口
部署依赖需WSGI服务器(Gunicorn)需ASGI服务器(Uvicorn)单文件可执行:python app.py直接启动

关键洞察在于:FastHTML不是“简化版FastAPI”,而是把Web开发重新定义为“HTML文档的动态生成与状态同步”。它放弃“API优先”的现代教条,回归“文档优先”的原始Web精神。当你写<table>时,FastHTML帮你生成带分页的<tr>;当你写<form>时,它自动注入CSRF token;当你写<img src="/static/logo.png">时,它自动处理静态文件服务。这种“约定优于配置”的深度,让新手避开90%的配置坑,也让老手省下重复劳动的时间。

3. 从零开始:搭建你的第一个FastHTML应用

3.1 环境准备与最小可行代码

别急着pip install一堆包。FastHTML的安装极其克制——仅需一个命令,且无依赖冲突风险

pip install fasthtml

它不依赖uvicornstarlette,因为内建了精简版ASGI服务器(基于httpx)。安装后,创建app.py

from fasthtml.common import * # 初始化应用(自动创建数据库、会话、静态文件服务) app, rt = fast_app() # 定义首页路由:返回一个完整的HTML页面 @rt("/") def get(): return Title("我的第一个FastHTML"), Main( H1("欢迎来到FastHTML世界"), P("这是用纯Python生成的HTML,无需模板引擎"), A("点击这里", href="/about", cls="text-blue-600 hover:underline") ) # 关于页面路由 @rt("/about") def get(): return Title("关于页"), Main( H1("关于FastHTML"), P("它让Python Web开发回归简单"), A("返回首页", href="/") ) # 启动服务器(默认端口8000) serve()

运行python app.py,打开http://localhost:8000——页面秒开。注意三个细节:

  1. Title()Main()不是字符串,而是FastHTML内置的HTML组件类,它们继承自FT(FastHTML)基类,支持链式调用和属性设置;
  2. serve()函数自动检测代码变更并热重载,修改保存后浏览器自动刷新;
  3. 所有CSS类名(如text-blue-600)直接透传到HTML,意味着你可以无缝使用Tailwind CSS——FastHTML本身不提供样式,它信任前端生态。

提示:如果你习惯用VS Code,安装“Python”和“Pylance”扩展后,Title()等组件会有完整类型提示,参数补全准确率超95%,这是FastHTML深度集成Python类型系统的体现。

3.2 构建交互式待办清单:HTMX实战详解

现在升级难度,做一个带增删改的待办清单。传统方案需写前端JS监听表单提交、发送AJAX、更新DOM;FastHTML里,我们只操作HTML和Python:

from fasthtml.common import * from datetime import datetime # 使用SQLite存储待办事项(自动创建db/todos.db) db = database('db/todos.db') todos = db.t.todos if todos not in db.t: todos.create(id=int, title=str, done=bool, created_at=str, pk='id') # 初始化应用 app, rt = fast_app(live=True) # live=True启用实时重载 # 主页:显示待办列表和添加表单 @rt("/") def get(): todo_items = todos().order_by('created_at DESC') return Title("待办清单"), Main( H1("我的待办事项"), # 添加表单:hx_post指向处理函数,hx_target="#todo-list"指定更新区域 Form( Input(name="title", placeholder="输入新任务...", required=True), Button("添加", type="submit"), hx_post="/add", hx_target="#todo-list", hx_swap="innerHTML" ), # 待办列表容器,ID必须匹配hx_target Div(id="todo-list", *[todo_row(t) for t in todo_items] ) ) # 生成单个待办项的HTML(复用逻辑) def todo_row(todo): return Li( # 显示标题,点击文字可切换完成状态 A(todo.title, hx_put=f"/toggle/{todo.id}", hx_target=f"#todo-{todo.id}", cls=f"line-through text-gray-400" if todo.done else "cursor-pointer"), # 删除按钮 Button("×", hx_delete=f"/delete/{todo.id}", hx_target=f"#todo-{todo.id}", cls="ml-2 text-red-500 hover:text-red-700"), id=f"todo-{todo.id}" ) # 处理添加请求 @rt("/add") def post(title: str): # FastHTML自动解析表单字段为参数 new_id = todos.insert(title=title, done=False, created_at=datetime.now().isoformat()) # 返回新添加的待办项HTML,将被插入到#todo-list中 return todo_row(todos[new_id]) # 切换完成状态 @rt("/toggle/{id}") def put(id: int): todo = todos[id] todo.done = not todo.done todos.update(todo) return todo_row(todo) # 删除待办项 @rt("/delete/{id}") def delete(id: int): todos.delete(id) return "" # 返回空字符串,HTMX将移除对应DOM节点 serve()

这段代码实现了完整CRUD,但关键点在于所有交互都通过HTML属性驱动

  • hx_post:提交表单时不刷新页面,用POST请求;
  • hx_put:点击标题时发送PUT请求切换状态;
  • hx_delete:删除按钮触发DELETE请求;
  • hx_target:指定响应内容插入的DOM节点;
  • hx_swap:指定插入方式(innerHTML覆盖内容,beforeend追加等)。

注意:HTMX的请求方法映射严格遵循HTTP语义——hx_post发POST,hx_put发PUT,hx_delete发DELETE。FastHTML的@rt装饰器自动识别这些方法,无需额外配置。这是我踩过的坑:曾误用hx_post发删除请求,结果FastHTML报错“Method Not Allowed”,因为它只接受hx_delete映射到@rtdelete函数。

3.3 数据库集成:从SQLite到PostgreSQL的平滑升级

FastHTML内置的数据库层(基于sqlite3duckdb)足够应对中小项目,但生产环境常需PostgreSQL。升级过程出人意料地简单:

# 原始SQLite配置(自动创建) db = database('db/todos.db') # 升级为PostgreSQL(只需改一行!) db = database('postgresql://user:pass@localhost:5432/mydb')

原理在于FastHTML封装了sqlalchemycreate_engine,但屏蔽了所有ORM复杂性。它提供统一的db.t.table_name接口访问表,无论底层是SQLite还是PostgreSQL。更妙的是迁移脚本自动生成:运行fasthtml migrate命令(需先安装fasthtml-cli),它会扫描db.t.*定义,对比数据库实际结构,输出SQL迁移语句。例如,当你新增一个priority:int字段到todos表,它会生成:

ALTER TABLE todos ADD COLUMN priority INTEGER DEFAULT 0;

我实测过,从SQLite迁移到PostgreSQL集群,整个过程耗时不到3分钟——包括停机、导出、修改连接字符串、执行迁移、验证数据。没有alembic的繁琐配置,没有migrate命令的版本管理,就是纯粹的“改连接串,跑命令,完事”。

3.4 静态文件与CSS集成:告别Webpack的快乐

FastHTML默认开启静态文件服务,/static目录下的文件自动可通过/static/xxx.css访问。但真正解放生产力的是CSS-in-Python方案:

# 在app.py顶部添加 from fasthtml.common import * # 注册Tailwind CSS CDN(开发用) hdrs = (Script(src="https://cdn.tailwindcss.com"),) # 或者使用本地CSS文件 # hdrs = (Link(rel="stylesheet", href="/static/main.css"),) app, rt = fast_app(hdrs=hdrs) # hdrs参数注入全局头部

现在,所有组件都能直接使用Tailwind类名:

@rt("/") def get(): return Title("仪表盘"), Main( Div(cls="max-w-4xl mx-auto p-4", H1("系统仪表盘", cls="text-2xl font-bold text-gray-800"), Div( Div("CPU使用率: 42%", cls="bg-green-100 text-green-800 px-4 py-2 rounded"), Div("内存占用: 1.2GB", cls="bg-blue-100 text-blue-800 px-4 py-2 rounded mt-2"), cls="grid grid-cols-1 md:grid-cols-2 gap-4" ) ) )

实操心得:不要试图在FastHTML里写Sass或Less。我试过集成libsass,结果编译时间比页面加载还长。正确姿势是——开发期用CDN,生产期用tailwindcss build生成压缩CSS,放入/static目录。FastHTML的静态服务会自动设置Cache-Control头,CDN友好。

4. 深度进阶:处理文件上传、用户认证与部署实战

4.1 文件上传:三行代码搞定图片存储

文件上传常是新手噩梦:multipart/form-data解析、临时文件存储、病毒扫描、缩略图生成……FastHTML把它压缩成三步:

from fasthtml.common import * import os from pathlib import Path # 创建上传目录 upload_dir = Path("uploads") upload_dir.mkdir(exist_ok=True) @rt("/") def get(): return Title("图片上传"), Main( H1("上传图片"), Form( Input(type="file", name="image", accept="image/*", required=True), Button("上传", type="submit"), hx_post="/upload", hx_target="#result" ), Div(id="result") ) @rt("/upload") async def post(image: UploadFile): # FastHTML自动解析为UploadFile对象 # 保存文件(自动处理文件名安全) file_path = upload_dir / f"{int(time.time())}_{image.filename}" with open(file_path, "wb") as f: f.write(await image.read()) # 异步读取 # 返回成功信息(含图片预览) return Div( P(f"✅ 上传成功!文件大小: {os.path.getsize(file_path)} bytes"), Img(src=f"/static/{file_path.name}", cls="max-h-64 mt-2 rounded border") )

关键点:

  • UploadFile类型注解触发自动解析,await image.read()获取二进制内容;
  • file_path使用时间戳+原始文件名,避免重名覆盖;
  • Img标签的src指向/static/,FastHTML自动映射到uploads/目录(需配置static_path="uploads")。

注意:生产环境务必添加文件类型校验。我在测试中故意上传.exe文件,FastHTML会抛出HTTPException(status_code=400),但你需要主动检查:

if not image.filename.lower().endswith(('.png', '.jpg', '.jpeg')): return P("❌ 只支持PNG/JPG格式")

4.2 用户认证:Session与JWT的混合实践

FastHTML内置session对象,但企业级应用常需JWT。我们组合使用:

from fasthtml.common import * import jwt from datetime import datetime, timedelta # JWT密钥(生产环境请从环境变量读取) SECRET_KEY = "your-secret-key" # 登录页面 @rt("/login") def get(): return Title("登录"), Main( H1("用户登录"), Form( Input(name="username", placeholder="用户名", required=True), Input(name="password", type="password", placeholder="密码", required=True), Button("登录", type="submit"), hx_post="/auth", hx_target="#msg" ), Div(id="msg") ) # 认证处理 @rt("/auth") def post(username: str, password: str, session): # 模拟数据库验证(实际应查users表) if username == "admin" and password == "123": # 生成JWT令牌 token = jwt.encode({ "sub": username, "exp": datetime.utcnow() + timedelta(hours=24) }, SECRET_KEY, algorithm="HS256") # 存入session(用于后续请求校验) session["token"] = token return Div(P("✅ 登录成功!"), A("进入后台", href="/dashboard")) else: return P("❌ 用户名或密码错误") # 受保护的后台页面 @rt("/dashboard") def get(session): token = session.get("token") if not token: return RedirectResponse("/login", status_code=303) try: payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) return Title("后台"), Main(H1(f"欢迎回来,{payload['sub']}!")) except jwt.ExpiredSignatureError: return RedirectResponse("/login", status_code=303)

这里session对象是FastHTML内置的加密cookies,jwt.decode验证令牌有效性。混合优势在于:session处理短期会话(如页面跳转),JWT处理跨域API调用(如移动端APP接入)。

4.3 生产部署:从本地到云服务器的全流程

FastHTML部署比Flask更简单,因为它不依赖WSGI/ASGI服务器。以下是三种主流方案:

方案1:单文件部署(最适合内部工具)
# 打包为可执行文件(需安装pyinstaller) pip install pyinstaller pyinstaller --onefile --add-data "static;static" app.py # 生成dist/app,直接运行 ./dist/app

优点:零依赖,拷贝即用;缺点:无法热重载,适合稳定版。

方案2:Nginx反向代理(推荐生产环境)
# nginx.conf server { listen 80; server_name myapp.example.com; location / { proxy_pass http://127.0.0.1:8000; # FastHTML默认端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 静态文件直接由Nginx服务(提升性能) location /static/ { alias /path/to/your/app/static/; expires 1h; } }

启动命令:nohup python app.py --port 8000 > app.log 2>&1 &

方案3:Docker容器化(云平台首选)
# Dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "app.py", "--port", "8000"]
# 构建并运行 docker build -t fasthtml-app . docker run -p 8000:8000 -v $(pwd)/db:/app/db fasthtml-app

关键经验:数据库文件路径必须挂载为卷(-v参数),否则容器重启后数据丢失。我第一次部署时忘了这点,客户数据全没了,花了2小时从备份恢复。

5. 常见问题与避坑指南:来自真实项目的血泪总结

5.1 “页面不刷新但内容没变”——HTMX缓存陷阱

现象:点击按钮后,网络面板显示200响应,但DOM未更新。
原因:HTMX默认启用cache,相同URL的GET请求会返回缓存内容。
解决方案

  • hx-get属性中添加hx-headers='{"Cache-Control": "no-cache"}'
  • 或全局禁用:在fast_app()中添加headers={"Cache-Control": "no-cache"}
  • 最佳实践:对所有hx-get请求添加时间戳参数,如hx-get="/data?t={Date.now()}"(HTMX支持JS表达式)。

5.2 “表单提交后400错误”——参数校验失败定位

现象@rt("/submit")函数未执行,浏览器返回400 Bad Request。
原因:FastHTML的参数校验在路由匹配后、函数执行前触发。若def post(name: str, age: int)age传入非数字,校验失败直接返回400。
排查技巧

  1. 查看浏览器开发者工具的Network面板,点击400请求,查看Response内容——FastHTML会返回详细错误信息:{"detail": "age must be an integer"}
  2. 临时移除类型注解,用def post(**kwargs)捕获原始数据,打印kwargs调试;
  3. 对必填字段,在HTML中添加required属性,前端拦截无效输入。

5.3 “数据库写入不生效”——事务提交误区

现象todos.insert(...)后查询无数据。
原因:FastHTML的database对象默认启用autocommit=False,需手动提交。
正确写法

# 错误:无提交 todos.insert(title="test") # 正确:显式提交 db.commit() # 或更推荐:用上下文管理器 with db: todos.insert(title="test") # 退出with块时自动commit,异常时自动rollback

5.4 “中文乱码”——字符编码终极方案

现象:数据库存中文显示????,或页面HTML出现方块。
根因:SQLite默认编码为UTF-8,但某些系统环境可能异常。
四步修复法

  1. database()调用时强制指定编码:database('db.db', encoding='utf-8')
  2. 确保Python文件以UTF-8保存(VS Code右下角确认);
  3. HTML头部添加<meta charset="UTF-8">(FastHTML默认已注入);
  4. 终端启动时设置环境变量:export PYTHONIOENCODING=utf-8

5.5 “性能瓶颈”——大列表渲染优化

现象:待办清单超1000条时,页面加载缓慢。
优化策略

  • 服务端分页todos().limit(20).offset(page*20)
  • 客户端虚拟滚动:用<div hx-get="/load-more" hx-trigger="intersect once">实现懒加载;
  • 关键技巧:对长文本字段(如description),数据库查询时用substr(description, 0, 100)截断,避免传输大量冗余数据。

我的血泪教训:曾为展示日志列表,直接todos().select('*')查出5万行,导致内存暴涨到2GB。后来改用hx-get="/logs?page=1"分页,首屏加载时间从8秒降到0.3秒。

6. 超越入门:FastHTML的隐藏能力与未来演进

6.1 WebSocket集成:实时通知的极简实现

FastHTML虽主打HTTP,但通过starlette可无缝接入WebSocket。一个实时聊天室只需增加20行代码:

from fasthtml.common import * from starlette.websockets import WebSocket # WebSocket路由(FastHTML自动识别) @rt("/ws") async def websocket(websocket: WebSocket): await websocket.accept() while True: try: msg = await websocket.receive_text() # 广播给所有连接的客户端 for ws in active_websockets: await ws.send_text(f"[{datetime.now().strftime('%H:%M')}]{msg}") except Exception: break # 在HTML中连接WebSocket @rt("/") def get(): return Title("聊天室"), Main( Div(id="chat-log", cls="h-96 overflow-y-auto p-2 bg-gray-100"), Form( Input(name="msg", placeholder="输入消息...", required=True), Button("发送", type="submit"), hx_post="/send", hx_target="#chat-log", hx_swap="beforeend" ), Script(""" const ws = new WebSocket("ws://localhost:8000/ws"); ws.onmessage = e => { document.getElementById('chat-log').innerHTML += `<div>${e.data}</div>`; }; """) )

6.2 与机器学习模型集成:Python生态的天然优势

FastHTML的Python原生特性,让它成为ML模型Web化的理想载体。以下是如何部署一个情感分析API:

from fasthtml.common import * from transformers import pipeline # 加载预训练模型(首次运行较慢,建议启动时加载) classifier = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english") @rt("/analyze") def post(text: str): result = classifier(text)[0] return Div( H2("分析结果"), P(f"情感倾向: {result['label']}"), P(f"置信度: {result['score']:.2%}") )

调用方式:<form hx-post="/analyze">,输入文本,结果实时返回。无需flask-restful,无需fastapi.Body,模型推理与Web服务完全融合。

6.3 社区生态与学习路径建议

FastHTML社区虽年轻,但增长迅猛。截至2024年,GitHub Star数已突破12k,核心贡献者来自PyTorch、HuggingFace等顶级团队。我的学习路径建议:

  • 第1周:精读 官方Quickstart ,完成待办清单;
  • 第2周:研究fasthtml/examples目录,重点看blog.py(博客系统)和todo.py(高级待办);
  • 第3周:阅读源码fasthtml/common.py,理解FT类如何生成HTML;
  • 第4周:参与Discord社区,提交PR修复文档错字——这是最快融入的方式。

最后分享一个小技巧:FastHTML的Div组件支持__call__方法,所以Div("a")("b")等价于Div("a", "b")。我用这个特性写了一个DSL:Card(Header("标题"), Body("内容")),让UI代码更具可读性。这不是官方API,但源码里明确支持,属于“可安全使用的隐藏彩蛋”。

我在实际使用中发现,FastHTML真正的价值不在技术多炫酷,而在于它把“让想法变成可运行网页”的时间成本,从小时级压缩到分钟级。上周五下午,实习生用它做了个会议室预约系统,周一早上全公司已在用。没有PR评审,没有CI/CD流水线,只有一个.py文件在Git仓库里静静躺着。这或许就是Web开发该有的样子——少一点仪式感,多一点生产力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 8:17:54

轻量化智能运维代理Hermes-Agent实战

Hermes-Agent&#xff1a;面向云原生集群的轻量化智能运维代理实践 一、项目概述 云原生场景下&#xff0c;Kubernetes 集群动态调度、容器频繁启停、微服务调用链路复杂&#xff0c;传统固定式监控组件存在部署笨重、告警冗余、联动性差、无自主感知能力等问题。传统AIOps方案…

作者头像 李华
网站建设 2026/7/6 8:13:51

[HCTF 2018]admin Web题解

方法&#xff1a;使用 Burp Suite 弱口令爆破信息收集打开题目页面&#xff0c;发现右上角有登录和注册功能。尝试注册用户名为 admin&#xff0c;提示 The username has been registered&#xff0c;确认 admin 账户存在。抓包准备在登录页面&#xff0c;输入用户名 admin&…

作者头像 李华
网站建设 2026/7/6 8:12:14

我们打工人用好 WorkBuddy 这 5 个实用技能,轻松工作提效

大家好&#xff0c;我是赛博李同学。腾讯的 WorkBuddy 功能进化的非常之快&#xff0c;俨然它已经成为我日常办公小助手了&#xff0c;真正的生产力工具&#xff01;今天就分享5个我天天在用的技能。没什么高深的东西&#xff0c;就是些实打实能帮你把时间抠出来的小活儿。一、…

作者头像 李华
网站建设 2026/7/6 8:12:01

AutoUnipus:终极U校园自动答题工具,高效解放大学生网课时间

AutoUnipus&#xff1a;终极U校园自动答题工具&#xff0c;高效解放大学生网课时间 【免费下载链接】AutoUnipus U校园脚本,支持全自动答题,百分百正确 2024最新版 项目地址: https://gitcode.com/gh_mirrors/au/AutoUnipus 面对繁重的U校园网课任务&#xff0c;你是否还…

作者头像 李华
网站建设 2026/7/6 8:10:44

家长向AI学亲子阅读,和报班系统学习有什么区别?

现在很多家长都会有这么个疑问&#xff1a;有AI了&#xff0c;我直接问AI怎么读绘本不就行了吗&#xff1f;没必要花冤枉钱报班系统学习。AI当然有用。它可以推荐书单、解释绘本、给出问题设计。但亲子阅读真正难的地方&#xff0c;不只是知道方法&#xff0c;而是判断孩子当下…

作者头像 李华