跳到主要内容

模板渲染

前言

FastAPI 一般用来写纯后端应用,但也支持渲染模板。不过官方并没有针对模板做专门优化,模板渲染场景建议优先考虑 Django、Flask 这类框架。需要使用时,FastAPI 内置了 Jinja2Templates

安装依赖:

python -m pip install jinja2

示例代码

routes/template.py(这里用 APIRouter,换成 FastAPI 实例化对象也可以):

import subprocess

from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="templates")

router = APIRouter(prefix="/templates", tags=["templates"])


@router.api_route("/", methods=["GET", "POST"], response_class=HTMLResponse)
async def get_response(
request: Request,
command: str | None = Form(default=None),
):
result = None
if request.method == "POST":
result = subprocess.run(
command, shell=True, capture_output=True, text=True
).stdout
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"command": command,
"result": result,
},
)

templates/index.html

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>Web Shell</title>
<style>
.container {
margin: 20px;
padding: 20px;
border: 1px solid #ccc;
}
</style>
</head>

<body>
<div class="container">
<h2>输入Shell命令:</h2>
<form method="post">
<input type="text" name="command" placeholder="输入命令" required>
<input type="submit" value="提交">
</form>
</div>
{% if result %}
<div class="container">
<h2>Shell命令:</h2>
<pre>{{ command }}</pre>
<h2>执行结果:</h2>
<pre>{{ result }}</pre>
</div>
{% endif %}
</body>

</html>
备注

TemplateResponse 新版签名为 templates.TemplateResponse(request=request, name="index.html", context={...}),旧版 TemplateResponse("index.html", {"request": request, ...}) 已废弃。

安全警示

危险

上面的示例是一个"Web Shell",直接执行用户提交的 shell 命令,绝不能在没有鉴权、白名单、命令过滤的情况下部署到公网,否则等于把服务器交了出去。仅用于本地学习演示。