简单絮叨一些
前面一篇文章唠了异常处理和路径操作配置,今天主要唠下依赖项
Fastapi中提供了依赖注入系统,怎么理解呢?
其实就是本来我是要接收很多参数来构造对象,现在我只接收一个已经实例化的对象。
网上很多的抽象解读,感觉看多了,都emo了,虽说上述总结的一句话比较狭义,但是并没有偏多少,主旨是存在的。
依赖注入常用于以下场景:
- 共享业务逻辑(复用相同的代码逻辑)
- 共享数据库连接
- 实现安全、验证、角色权限
- 等……
上述场景均可以使用依赖注入,将代码重复最小化。
依赖项
初识依赖项
依赖项的使用必须要导入Depends,它是Fastapi提供的专门处理依赖的
import uvicornfrom typing import Optionalfrom fastapi import FastAPIfrom fastapi import Dependsapp = FastAPI()def common_parameters(q: Optional[str] = None, skip: int = 0, limit: int = 10): return {"q": q, "skip": skip, "limit": limit}@app.get("/items/")def read_items(commons: dict = Depends(common_parameters)): return commons@app.get("/users/")def read_user(commons: dict = Depends(common_parameters)): return commonsif __name__ == '__main__': uvicorn.run(app="dependency_main:app", reload=True, debug=True)
注释信息:
- from fastapi import Depends导入依赖项
- commons: dict = Depends(common_parameters)声明依赖项
注意点:
- Depends中的参数必须是可调用对象,比如函数等。
子依赖项
Fastapi支持创建含子依赖项的依赖项,并且,可以按需声明任意深度的子依赖项嵌套层级。
import uvicornfrom typing import Optionalfrom fastapi import FastAPIfrom fastapi import Dependsfrom fastapi import Cookieapp = FastAPI()def parent_parameters(q: Optional[str] = None): return qdef child_parameters(q: str = Depends(parent_parameters), last_query: Optional[str] = Cookie(None)): if not q: return last_query return q@app.get("/default/")def read_default(query_or_default: str = Depends(child_parameters)): return {"q_or_cookie": query_or_default}@app.get("/default_more/")def read_default_more(query_or_default: str = Depends(child_parameters, use_cache=False)): return {"q_or_cookie": query_or_default}if __name__ == '__main__': uvicorn.run(app="dependency_main:app", reload=True, debug=True)
注释信息:
- parent_parameters函数就是返回一个q
- child_parameters函数是根据q是否传参数,然后返回对应信息
- query_or_default: str = Depends(child_parameters)声明依赖项
- use_cache=False如果不想使用「缓存」值,而是为需要在同一请求的每一步操作(多次)中都实际调用依赖项,可以把 Depends 的参数 use_cache 的值设置为 False
注意点:
- 含子依赖项的会先处理第一层,然后再处理第二层,因为第二层依赖第一层,比如:上述例子在请求接口时会先处理parent_parameters函数,然后再处理child_parameters函数,因为child_parameters需要parent_parameters函数的返回值。
类作为依赖项*
类作为依赖项,其实就是函数作为依赖项的升级版,那这里的类因为注入依赖系统的存在,是不需要进行实例化对象的,只需
要把类名传入,Fastapi会自动分析是不是可调用的参数,如果是可调用的 则以与路径操作函数的参数相同的方式处理它们。
import uvicornfrom typing import Optionalfrom fastapi import FastAPIfrom fastapi import Dependsfrom fastapi import Cookieapp = FastAPI()fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]class CommonParameters: def __init__(self, q: Optional[str] = None, skip: int = 0, limit: int = 100): self.q = q self.skip = skip self.limit = limit@app.get("/object/")def read_object(commons: CommonParameters = Depends(CommonParameters)): response = {} if commons.q: response.update({"q": commons.q}) response.update({"name": "lifeng"}) items = fake_items_db[commons.skip: commons.skip + commons.limit] response.update({"items": items}) return response
注释信息:
- CommonParameters是定义的类,并定义了一些属性(如:self.q = q等)
- commons: CommonParameters = Depends(CommonParameters)证明依赖项,只传类名即可
- if commons.q:是判断q是否传参
- response.update({"q": commons.q})是把q更新至response字典中
- fake_items_db[commons.skip: commons.skip + commons.limit]是切片取值后赋值给items
- response.update({"items": items})是把items更新至response字典中
注意点:
- commons: CommonParameters = Depends(CommonParameters)也可以写成commons = Depends(CommonParameters)或者写成commons: CommonParameters = Depends()
路径操作装饰器依赖项
1 - 在路径操作装饰器中添加 dependencies 参数
有时,我们并不需要在路径操作函数中使用依赖项的返回值。或者说,有些依赖项不返回值。那就可以在路径操作装饰器中添加一个由 dependencies 组成的 list。
2 - 依赖项错误和返回值
依赖项也可以在路径定义需求项(比如请求头),也可以抛出异常或者return返回值(无论路径装饰器依赖项是否返回值,路径操作都不会使用这些值。)
import uvicornfrom fastapi import FastAPIfrom fastapi import Dependsfrom fastapi import Headerfrom fastapi import HTTPExceptionapp = FastAPI()def verify_token(x_token: str = Header(...)): if x_token != "li_feng_token": raise HTTPException(status_code=400, detail="x_token 未定义!")def verify_key(x_key: str = Header(...)): if x_key != "li_feng_key": raise HTTPException(status_code=400, detail="x_key 未定义!") return x_key@app.get("/handle_path/", dependencies=[Depends(verify_token), Depends(verify_key)])def read_handle_path(): return [ {"item": "Foo"}, {"item": "Bar"} ]if __name__ == '__main__': uvicorn.run(app="dependency_main:app", reload=True, debug=True)
全局依赖项
有时,我们要为整个应用添加依赖项。那就得把依赖项添加至整个 FastAPI 应用。这些依赖项可以用于应用中的所有路径操作。
import uvicornfrom fastapi import Headerfrom fastapi import FastAPIfrom fastapi import Dependsfrom fastapi import HTTPExceptiondef verify_token(x_token: str = Header(...)): if x_token != "li_feng_token": raise HTTPException(status_code=400, detail="x_token 未定义!")def verify_key(x_key: str = Header(...)): if x_key != "li_feng_key": raise HTTPException(status_code=400, detail="x_key 未定义!") return x_keyapp = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])@app.get("/items_global/")def read_items_global(): return [{"item": "Portal Gun"}, {"item": "Plumbus"}]@app.get("/users_global/")def read_users_global(): return [{"username": "Rick"}, {"username": "Morty"}]if __name__ == '__main__': uvicorn.run(app="dependencies_global_main:app", reload=True, debug=True)
注释信息:
- app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])设置全局依赖项
今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!
未完成,待续……
一直在努力,希望你也是!
微信搜索公众号:就用python
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除