接收的不是 JSON,而是表单字段时,要使用 Form
。
表单数据的「媒体类型」编码一般为 application/x-www-form-urlencoded
。
要使用表单,需预先安装 python-multipart
。
pip install python-multipart
与 JSON 不同,HTML 表单(<form></form>
)向服务器发送数据通常使用「特殊」的编码。
FastAPI 要确保从正确的位置读取数据,而不是读取 JSON。
可在一个路径操作中声明多个
Form
参数,但不能同时声明要接收 JSON 的Body
字段。因为此时请求体的编码是application/x-www-form-urlencoded
,不是application/json
。 这不是 FastAPI 的问题,而是 HTTP 协议的规定。
Form
从 fastapi
导入 Form
:
from fastapi import FastAPI, Form
创建表单(Form
)参数的方式与 Body
和 Query
一样(Form
是直接继承自 Body
的类。):
async def login(username: str = Form(), password: str = Form()):
例如,OAuth2 规范的 “密码流” 模式规定要通过表单字段发送 username
和 password
。
该规范要求字段必须命名为 username
和 password
,并通过表单字段发送,不能用 JSON。
使用 Form
可以声明与 Body
(及 Query
、Path
、Cookie
)相同的元数据和验证。
需安装jinja2模板
pip install jinja2
在项目根目录创建 templates 模板目录 ![[Pasted image 20230901170025.png]] 前面html代码
<!DOCTYPE html> <html lang="en"> <head>
<meta charset="UTF-8">
<title>登录</title> </head> <body>
<form method="post">
<p>{{login_tip}}</p>
<div>
<label for="username">请输入用户名</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="password">请输入用户名</label>
<input type="password" id="password" name="password">
</div>
<input type="submit" value="提交">
</form> </body> </html>
Form 表单提交
from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
app.mount(
"/static",
StaticFiles(directory="static"),
name="static" )
templates = Jinja2Templates(directory="templates")
@app.get("/login/", response_class=HTMLResponse) async def read_item(request: Request):
print(request.method)
return templates.TemplateResponse(
"login.html", context={
'request': request, 'login_tip': '用户登录'
}
)
@app.post("/login/") async def login(
username: str = Form(),
password: str = Form() ):
return {"username": username}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
app='main:app',
host="127.0.0.1",
port=8000, reload=True
)