- 请求方式
- 不同请求方式下的参数获取方式
请求方式
FastAPI请求方式通过实例化FastAPI对象点属性来控制
单个请求方式
from fastapi import FastAPIapp = FastAPI()@app.get("/get/")def get():# GET请求return {"action": "GET"}@app.post("/post/")def post():# POST请求return {"action": "POST"}@app.put("/put/")def put():# PUT请求return {"action": "PUT"}@app.delete("/delete/")def delete():# DELETE请求return {"action": "DELETE"}
启动服务后,使用requests测试:
import requestsprint(requests.get("http://localhost:8000/get").json())# {'action': 'GET'}print(requests.post("http://localhost:8000/post/").json())# {'action': 'POST'}print(requests.put("http://localhost:8000/put/").json())# {'action': 'PUT'}print(requests.delete("http://localhost:8000/delete/").json())# {'action': 'DELETE'}print(requests.post("http://localhost:8000/get").json())# {'detail': 'Method Not Allowed'}
多种请求方式
这里使用api_route属性,由FastAPI类提供(继承自Starlette)
编写路由为http://127.0.0.1:8000/action/的接口,同时支持GET、POST、PUT、DELETE四种请求方式:
from fastapi import FastAPIfrom starlette.requests import Requestfrom starlette.responses import JSONResponse# 方式一@app.api_route("/action/", methods=["GET", "POST", "PUT", "DELETE"])def action(request: Request):return {"action": request.method}# 方式二:也可使用父类提供的route属性@app.route("/action/", methods=["GET", "POST", "PUT", "DELETE"])def action(request: Request):return JSONResponse({"action": request.method})
❕注意项:
使用父类route属性时,因为其内部并没有像Fast API那样额外封装支撑
所以在使用时:request参数为必填项,响应结果也必须为Response类型。
分别请求响应为:
print(requests.get("http://localhost:8000/action/").json())# {'action': 'GET'}print(requests.post("http://localhost:8000/action/").json())# {'action': 'POST'}print(requests.put("http://localhost:8000/action/").json())# {'action': 'PUT'}print(requests.delete("http://localhost:8000/action/").json())# {'action': 'DELETE'}
路径参数
在路由里,通过{}标识获取
示例如下:
from fastapi import FastAPI@app.get("/book/{book_id}")def book(book_id: int):"""书籍📚"""return {"id": book_id}
❕注意项:
- 函数参数必须包含路径参数,否则会被认为是查询Query参数,导致路径参数无效果
- 因为在定义函数时,指定了book_id为int类型,FastAPI会自动校验其传入值是否符合(若对类型无要求,可不指定)
测试请求响应为:
import requestsprint(requests.get("http://localhost:8000/book/1/").json())# {'id': 1}print(requests.get("http://localhost:8000/book/test/").json())# {'detail': [{'loc': ['path', 'book_id'], 'msg': 'value is not a valid integer', 'type': 'type_error.integer'}]}
查询参数(Query参数)
查询参数中存在多种情况,如必选、非必选、默认值…
FastAPI提供简单的参数控制,将Python函数的参数定义方式结合到Web参数控制上,一定程度上简化了开发效率,节省了额外的参数校验工作。
接下来,分别定义多种参数,来看它们的实现方式:
from fastapi import FastAPIfrom typing import Optional@app.get("/books/")def books(book_type: str, limit: int = 1, size: int = 10, book_name: Optional[str] = None, sort: bool = False):return {"book_type": book_type,"book_name": book_name,"sort": sort,"limit": limit,"size": size}
这个例子定义了四种不同性质的Query参数:
- book_type:字符串,必选
- limit、size:整型,非必选,且提供默认值
- book_name:字符串,非必选,默认值为None
- sort:布尔类型,非必选,默认值为False
❕注意项:
因为都指定了相应的数据类型,因此,FastAPI会做基本的数据类型校验和类型强制转换。如:
- limit为整型,传入字符串会导致强转失败,导致接口返回类型错误的提示信息。
- sort为布尔值,不论传入字符串,还是整型,都可以强转为True或False。
分别测试请求响应为:
import requestsprint(requests.get("http://localhost:8000/books/").json())# {'detail': [{'loc': ['query', 'book_type'], 'msg': 'field required', 'type': 'value_error.missing'}]}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍"}).json())# {'book_type': 'IT书籍', 'book_name': None, 'sort': False, 'limit': 1, 'size': 10}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍", "book_name": "数学之美"}).json())# {'book_type': 'IT书籍', 'book_name': '数学之美', 'sort': False, 'limit': 1, 'size': 10}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍", "book_name": "数学之美", "limit": 2, "size": 20}).json())# {'book_type': 'IT书籍', 'book_name': '数学之美', 'sort': False, 'limit': 2, 'size': 20}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍", "book_name": "数学之美", "limit": "limit", "size": "size"}).json())# {'detail': [{'loc': ['query', 'limit'], 'msg': 'value is not a valid integer', 'type': 'type_error.integer'}, {'loc': ['query', 'size'], 'msg': 'value is not a valid integer', 'type': 'type_error.integer'}]}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍", "book_name": "数学之美", "sort": True}).json())# {'book_type': 'IT书籍', 'book_name': '数学之美', 'sort': True, 'limit': 1, 'size': 10}print(requests.get("http://localhost:8000/books/", params={"book_type": "IT书籍", "book_name": "数学之美", "sort": 1}).json())# {'book_type': 'IT书籍', 'book_name': '数学之美', 'sort': True, 'limit': 1, 'size': 10}
Body参数
获取并操作body参数,Fast API提供两种方式。通过定义Pydantic模型和使用Body参数
Pydantic模型
需要先声明Pydantic模型,通过定义的属性来获取和校验body参数
定义方式如下:
from fastapi import FastAPIfrom pydantic import BaseModelfrom typing import Optional# 定义Pydantic模型class Book(BaseModel):name: strtype: Optional[str] = "其他"price: intapp = FastAPI()@app.post("/book/")# 参数声明def create_book(book: Book):book_dict = book.dict()if book.price > 100:book_dict.update({"buy": "哦~,我买不起"})else:book_dict.update({"buy": "哈哈,我能买的起!!"})return book_dict
通过继承BaseModel,定义Pydantic模型类
然后将其声明为参数,同时,Fast API会将请求体作为json读取,根据指定的模型类校验或转换数据类型。验证通过后,将数据赋值给参数
book在获取到body参数后,可在函数内部访问模型对象的所有属性
测试请求响应为:
import requestsbody = {"name": "数学之美"}print(requests.post("http://localhost:8000/book/", json=body).json())# {'detail': [{'loc': ['body', 'price'], 'msg': 'field required', 'type': 'value_error.missing'}]}body = {"name": "数学之美", "price": 1}print(requests.post("http://localhost:8000/book/", json=body).json())# {'name': '数学之美', 'type': '其他', 'price': 1, 'buy': '哈哈,我能买的起!!'}body = {"name": "数学之美", "price": 1000}print(requests.post("http://localhost:8000/book/", json=body).json())# {'name': '数学之美', 'type': '其他', 'price': 1000, 'buy': '哦~,我买不起'}body = {"name": "数学之美", "price": 1, "type": "IT书籍"}print(requests.post("http://localhost:8000/book/", json=body).json())# {'name': '数学之美', 'type': 'IT书籍', 'price': 1, 'buy': '哈哈,我能买的起!!'}
Body参数
小结
- 当同一个路由,同时存在路径参数、查询参数、body参数时,FastAPI匹配顺序如下:
- 如果在路径中也声明了该参数,它将被用作路径参数。
- 如果参数属于单一类型(比如
int、float、str、bool等)它将被解释为查询参数。 - 如果参数的类型被声明为一个 Pydantic 模型,它将被解释为请求体。
