diff --git a/docs/fastapi.md b/docs/fastapi.md index 917e318..4f0dfb0 100644 --- a/docs/fastapi.md +++ b/docs/fastapi.md @@ -5,7 +5,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框 入门 --- -<!--rehype:body-class=cols-1--> +<!--rehype:body-class=cols-2--> ### 最小程序 @@ -16,7 +16,11 @@ from fastapi import FastAPI import uvicorn app = FastAPI() +``` +添加一个 API 的示例 + +```python # http://127.0.0.1:8000/ @app.get("/") async def root(): @@ -65,12 +69,14 @@ async def read_item(file_path): ``` ### 查询参数 +<!--rehype:wrap-class=row-span-2--> #### 带默认值的查询参数 ```python # http://127.0.0.1:8000/items/?skip=0&limit=2 -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] +fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}] + @app.get("/items/") async def read_item(skip: int = 0, limit: int = 10): return fake_items_db[skip: skip + limit] @@ -81,6 +87,7 @@ async def read_item(skip: int = 0, limit: int = 10): ```python # http://127.0.0.1:8000/items/1?q=admin from typing import Union + @app.get("/items/{item_id}") async def read_item(item_id: str, q: Union[str, None] = None): if q: @@ -96,14 +103,17 @@ async def read_item(item_id: str, q: Union[str, None] = None): # http://127.0.0.1:8000/users/1/items/2?q=query&short=true @app.get("/users/{user_id}/items/{item_id}") async def read_user_item( - user_id: int, item_id: str, q: Union[str, None] = None, short: bool = False + user_id: int, + item_id: str, + q: Union[str, None] = None, + short: bool = False ): item = {"item_id": item_id, "owner_id": user_id} if q: item.update({"q": q}) if not short: item.update( - {"description": "This is an amazing item that has a long description"} + {"description": "这是一个令人惊叹的项目,有很长的描述"} ) return item ``` @@ -154,7 +164,9 @@ curl -X 'POST' \ ```python from fastapi import Query @app.get("/items/") -async def read_items(q: Union[str, None] = Query(default=None, max_length=50)): +async def read_items( + q: Union[str, None] = Query(default=None, max_length=50) +): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) @@ -177,14 +189,16 @@ async def read_items(q: Union[str, None] = Query(default=None, max_length=50)): ```python # http://127.0.0.1:8000/items/?q=foo&q=bar @app.get("/items/") -async def read_items(q: Union[List[str], None] = Query(default=None)): +async def read_items( + q: Union[List[str], None] = Query(default=None) +): query_items = {"q": q} return query_items ``` ### 路径参数和数值校验 -Path用法基本和Query相同,参考:[FastAPI官方文档](https://fastapi.tiangolo.com/zh/tutorial/path-params-numeric-validations/) +Path 用法基本和 Query 相同,参考:[FastAPI官方文档](https://fastapi.tiangolo.com/zh/tutorial/path-params-numeric-validations/) #### 导入 Path @@ -198,8 +212,8 @@ from typing_extensions import Annotated ```python @app.get("/items/{item_id}") async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get")], - q: Annotated[Union[str, None], Query(alias="item-query")] = None, + item_id: Annotated[int, Path(title="要获取的项目的 ID")], + q: Annotated[str | None, Query(alias="item-query")] = None, ): results = {"item_id": item_id} if q: @@ -220,14 +234,16 @@ async def read_items( ### 其他参数 -都具有Query的参数,max_length、min_length等 +都具有 Query 的参数,max_length、min_length等 #### Cookie参数 ```python from fastapi import Cookie @app.get("/items/") -async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None): +async def read_items( + ads_id: Annotated[Union[str, None], Cookie()] = None +): return {"ads_id": ads_id} ``` @@ -236,7 +252,10 @@ async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None): ```python from fastapi import Header @app.get("/items/") -async def read_items(user_agent: Annotated[Union[str, None], Header()] = None,items_id: Annotated[Union[int, None], Header(ge=1)] = None): +async def read_items( + user_agent: Annotated[Union[str, None], Header()] = None, + items_id: Annotated[Union[int, None], Header(ge=1)] = None +): return {"User-Agent": user_agent, "items_id": items_id} ``` @@ -320,8 +339,7 @@ async def main(): 依赖项 --- - -<!--rehype:body-class=cols-1--> +<!--rehype:body-class=cols-2--> ### 依赖项使用场景 @@ -331,6 +349,7 @@ async def main(): - 等…… ### 创建依赖项 +<!--rehype:wrap-class=row-span-2--> ```python from typing import Union @@ -338,22 +357,31 @@ from typing import Union from fastapi import Depends, FastAPI app = FastAPI() +``` -# read_items和read_users方法依赖common_parameters -# 白话就是read_items和read_users都需要q,skip,limit查询参数 +`read_items` 和 `read_users` 方法依赖 `common_parameters` +白话就是 `read_items` 和 `read_users` 都需要 `q`,`skip`,`limit` 查询参数 + +```python async def common_parameters( - q: Union[str, None] = None, skip: int = 0, limit: int = 100 + q: Union[str, None] = None, + skip: int = 0, + limit: int = 100 ): return {"q": q, "skip": skip, "limit": limit} @app.get("/items/") -async def read_items(commons: dict = Depends(common_parameters)): +async def read_items( + commons: dict = Depends(common_parameters) +): return commons @app.get("/users/") -async def read_users(commons: dict = Depends(common_parameters)): +async def read_users( + commons: dict = Depends(common_parameters) +): return commons ``` @@ -361,60 +389,66 @@ async def read_users(commons: dict = Depends(common_parameters)): ```python from typing import Union - from fastapi import Depends, FastAPI app = FastAPI() - - -fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] - +fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}] class CommonQueryParams: - def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100): + def __init__( + self, + q: Union[str, None] = None, + skip: int = 0, + limit: int = 100 + ): self.q = q self.skip = skip self.limit = limit +``` -# read_itemsx接收一个commons参数,类型是CommonQueryParams -# CommonQueryParams接收三个参数,这三个参数是调用api的时候传 +`read_itemsx` 接收一个 `commons` 参数,类型是 `CommonQueryParams` +`CommonQueryParams` 接收三个参数,这三个参数是调用 api 的时候传 + +```python @app.get("/items/") -async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response +async def read_items( + commons: CommonQueryParams = Depends(CommonQueryParams) +): + response = {} + if commons.q: + response.update({"q": commons.q}) + items = fake_items_db[commons.skip : commons.skip + commons.limit] + response.update({"items": items}) + return response ``` #### 还可以简写 ```python @app.get("/items/") -async def read_items(commons: CommonQueryParams = Depends()): # 这里的Depends没有传参,FastAPI会自动使用CommonQueryParams - response = {} - if commons.q: - response.update({"q": commons.q}) - items = fake_items_db[commons.skip : commons.skip + commons.limit] - response.update({"items": items}) - return response +async def read_items( + # 这里的 Depends 没有传参,FastAPI 会自动使用 CommonQueryParams + commons: CommonQueryParams = Depends() +): + response = {} + if commons.q: + response.update({"q": commons.q}) + items = fake_items_db[commons.skip : commons.skip + commons.limit] + response.update({"items": items}) + return response ``` ### 子依赖项 ```python from typing import Union - from fastapi import Cookie, Depends, FastAPI app = FastAPI() - def query_extractor(q: Union[str, None] = None): return q - def query_or_cookie_extractor( q: str = Depends(query_extractor), last_query: Union[str, None] = Cookie(default=None), @@ -427,20 +461,25 @@ def query_or_cookie_extractor( # query_or_cookie_extractor函数又依赖query_extractor函数 # 就是说依赖项可以依赖其他依赖项,只要你不晕,可以无数次套娃 @app.get("/items/") -async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): +async def read_query( + query_or_default: str = Depends(query_or_cookie_extractor) +): return {"q_or_cookie": query_or_default} ``` #### 不使用缓存 +使用 `use_cache = False` 参数不使用缓存数据,不使用 `use_cache = False`,`value` 和 `value1` 是一样的 + ```python -# 使用use_cache = False参数不使用缓存数据 -# 不使用use_cache = False,value和value1是一样的 def result_value(): value = randint(1, 99) return value -def get_value(value: int = Depends(result_value, use_cache=False), value1: int = Depends(result_value, use_cache=False)): +def get_value( + value: int = Depends(result_value, use_cache=False), + value1: int = Depends(result_value, use_cache=False) +): return value, value1 @app.get('/value/') @@ -453,26 +492,27 @@ async def needy_dependency(value: tuple = Depends(get_value)): ```python from fastapi import Depends, FastAPI, Header, HTTPException - async def verify_token(x_token: str = Header()): - if x_token != "fake-super-secret-token": - raise HTTPException(status_code=400, detail="X-Token header invalid") - + if x_token != "fake-super-secret-token": + raise HTTPException(status_code=400, detail="X-Token 标头无效") async def verify_key(x_key: str = Header()): - if x_key != "fake-super-secret-key": - raise HTTPException(status_code=400, detail="X-Key header invalid") - return x_key + if x_key != "fake-super-secret-key": + raise HTTPException(status_code=400, detail="X-Key 标头无效") + return x_key +``` -# 全局依赖项很有用,后面的安全性就可以使用全局依赖项 -app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)]) +全局依赖项很有用,后面的安全性就可以使用全局依赖项 +```python +app = FastAPI( + dependencies=[Depends(verify_token), Depends(verify_key)] +) @app.get("/items/") async def read_items(): return [{"item": "Portal Gun"}, {"item": "Plumbus"}] - @app.get("/users/") async def read_users(): return [{"username": "Rick"}, {"username": "Morty"}]