FastAPI API 文档界面定制指南:3步自托管 CSS 与 2 个主题配置场景
【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi
FastAPI 生成的/docs与/redoc页面,默认从外部 CDN 拉取 Swagger UI 和 ReDoc 的 JS、CSS,样式不可动。如果你的服务部署在内网,或希望文档页贴合公司品牌色,不需要改框架内部——替换资源地址、注入自己的 CSS 即可,所需的钩子 FastAPI 都留好了。
最终效果
完成自托管后,打开/docs依旧是那个 Swagger UI 界面,但swagger-ui-bundle.js、swagger-ui.css、redoc.standalone.js全部来自你自己的/static路径;请求体里的 JSON 示例换成 obsidian 高亮主题,顶栏和 "Try it out" 按钮由你的 CSS 重新上色。浏览器 Network 面板里不再出现任何外部 CDN 的请求。
最短路径
最小配置只做三件事:关掉内置文档、挂载静态目录、注册自己的/docs路由。核心函数在 fastapi/openapi/docs.py 里,完整写法可参考 docs_src/custom_docs_ui/tutorial002_py310.py。
第一行,禁用内置文档路由,把/docs和/redoc收归自己管理:
from fastapi import FastAPI app = FastAPI(docs_url=None, redoc_url=None) # 关掉内置 /docs、/redoc把static/目录挂到/staticURL 上,让浏览器能访问 CSS 文件:
from fastapi.staticfiles import StaticFiles app.mount("/static", StaticFiles(directory="static"), name="static")注册自定义/docs,把 CSS 指向本地文件:
from fastapi.openapi.docs import get_swagger_ui_html @app.get("/docs", include_in_schema=False) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_url=app.openapi_url, title=app.title + " - Swagger UI", swagger_css_url="/static/swagger-ui.css", # 指向本地 CSS )品牌样式写在自己的 CSS 里,直接追加热好的swagger-ui.css末尾即可覆盖同名规则:
/* 覆盖官方 swagger-ui.css 中的同名规则 */ .swagger-ui .topbar { background-color: #2c3e50; } .swagger-ui .info h2 { color: #3498db; }有一个硬约束:get_swagger_ui_html生成的 HTML 里只有一个<link>CSS 位,所以"官方 CSS + 自定义 CSS"必须合并成一份文件交付,另开一个styles.css是没人会引用的。
场景化方案
场景一:内网/离线环境全量自托管 📦
公司网络访问不了任何公网地址时,把 Swagger UI 和 ReDoc 三个文件全部下载到static/,走本地路径:
from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, get_swagger_ui_oauth2_redirect_html, ) app = FastAPI(docs_url=None, redoc_url=None) app.mount("/static", StaticFiles(directory="static"), name="static") @app.get("/docs", include_in_schema=False) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_url=app.openapi_url, title=app.title + " - Swagger UI", oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, swagger_js_url="/static/swagger-ui-bundle.js", swagger_css_url="/static/swagger-ui.css", )ReDoc 侧只需换 JS 地址(它的样式打包在 standalone 文件里,没有独立的 CSS 参数):
@app.get("/redoc", include_in_schema=False) async def redoc_html(): return get_redoc_html( openapi_url=app.openapi_url, title=app.title + " - ReDoc", redoc_js_url="/static/redoc.standalone.js", )注意:如果 API 用了 OAuth2 的 Authorize 按钮,必须同时注册get_swagger_ui_oauth2_redirect_html()对应的回调路由,否则授权流程会断在最后一步。
场景二:品牌 VI 统一,切换 Swagger UI 语法高亮主题 🎨
大多数团队不想大改界面,只希望高亮配色和代码风格统一。swagger_ui_parameters会原样透传给 Swagger UI,构造时传一个字典就行:
from fastapi import FastAPI # theme 取 highlight.js 内置主题名,如 arta、monokai、nord、obsidian app = FastAPI( swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}} )顶栏、按钮等结构性样式则交给上面的自定义 CSS 接管。两个入口一个管"高亮配色",一个管"整体视觉",互不干扰。
场景三:生产环境钉住静态资源版本
默认配置里 CDN 地址用的是swagger-ui-dist@5这种浮动版本,上游发新版后你的文档页样式会悄悄变化。自托管正好解决这个问题——版本由你下载哪个 release 决定:
app = FastAPI(docs_url=None) @app.get("/docs", include_in_schema=False) async def custom_swagger_ui_html(): return get_swagger_ui_html( openapi_url=app.openapi_url, title=app.title + " - Swagger UI", swagger_js_url="/static/swagger-ui-bundle.js", swagger_css_url="/static/swagger-ui.css", )注意:swagger_js_url和swagger_css_url必须来自同一个 release。混用不同版本会出现按钮错位、响应区塌陷这类样式漂移,且控制台不会报任何错。
对比与验证
| 项目 | 默认状态 | 自托管 + 定制后 |
|---|---|---|
| CSS 来源 | jsdelivr CDN | 本地/static/swagger-ui.css |
| 请求体 JSON 高亮 | highlight.js 默认主题 | obsidian 橙红色主题 |
| 顶栏 / 按钮配色 | 官方默认蓝 | 自己 CSS 定义的品牌色 |
默认主题下,示例值里的字符串是绿色:
换成syntaxHighlight.theme = "obsidian"后,同一位置的字符串变成橙红色:
验证方法:打开浏览器 Network 面板刷新/docs,确认swagger-ui.css、swagger-ui-bundle.js的请求来源是127.0.0.1:8000/static/...而非 CDN 域名。更多细节见 Custom Docs UI Static Assets 官方文档 和 Configure Swagger UI 官方文档。
高频坑排查
现象:
TypeError: __init__() got an unexpected keyword argument 'swagger_css_url'→ 原因:swagger_css_url、swagger_js_url是get_swagger_ui_html()的参数,不是FastAPI()构造函数的参数,直接传给FastAPI()必然报错 → 解法:按"禁用内置路由 + 自定义/docs路由"的流程走,资源地址在get_swagger_ui_html()里指定。现象:启动即抛
RuntimeError: Directory 'static' does not exist→ 原因:StaticFiles默认在启动时校验目录存在(check_dir=True) → 解法:先把static/目录建好、把三个文件下载进去再启动服务;check_dir=False虽然能绕过,但页面加载时照样 404,不要这么干。现象:改了配置,Network 里仍出现 jsdelivr 的
swagger-ui.css请求→ 原因:创建FastAPI()时没有传docs_url=None, redoc_url=None,内置/docs路由在构造时已注册且先于自定义路由匹配,你的自定义路由根本没被命中 → 解法:构造时显式置None禁用内置文档,再用 Network 面板复查资源来源。
自托管解决"连得上",swagger_ui_parameters解决"看得顺",自己的 CSS 解决"像自己家"。如果现在就要动手,最划算的顺序是:先切一个syntaxHighlight主题让高亮跟上团队风格,再把 CDN 资源逐步搬进/static——Network 面板里 jsdelivr 请求归零的那一刻,改造就算完成。
【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考