FastAPI--依賴注入之Depends(8)


一、概述

看官網的描述Depends的使用,似乎比較懵懵懂懂的,於是乎還是需要花些時間再次學習一下關於依賴注入。

首先依賴注入它可以是函數也可以是類,如下面的函數形式的依賴注入:

 

簡單的依賴說明

import uvicorn
from fastapi import Depends, FastAPI

app = FastAPI()

async def common_parameters(q: str = 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)):
    commons.update({'小鍾': '同學'})
    return commons

@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return commons

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

梳理一下接口請求的流程:

  • 1: 上面的commons: dict = Depends(common_parameters)它聲明了一個依賴關系: Depends(common_parameters): 這對接口的依賴進行了一個聲明,表示的是接口參數請求依賴於common_parameters的函數。

    當接口被調用的時候,回調用common_parameters函數進行請求處理。

  • 2: common_parameters函數主要是負責接收函數,處理后返回一個字典,

  • 3:然后把Depends(common_parameters)返回的結果 傳遞給commons: dict,這個就是一個依賴注入的過程。

所以在上面的示例中common_parameters是我們被依賴對象

這個被依賴的對象,對接口請求的要求就是:

  • 可選查詢參數q那是一個str.

  • 可選查詢參數skip那是int,默認情況下是0.

  • 可選查詢參數limit那是int,默認情況下是100.

  • 返回一個字典

請求示例:

http://127.0.0.1:8000/items/

 

 

 

這依賴注入的方式其實也挺方便,類似於接口裝飾器的方式,比如common_parameters中我們可以先對相關的參數進行校驗攔截,還可以再傳遞。 場景可以和我們之前的bottle的裝飾器差不多類似:

  • 相同的邏輯判斷處理

  • 用戶身份鑒權

 

把類當作被依賴對象

上面我們的被依賴的對象是以函數的形式出現,那FastAPI它也支持以類的形式來表達。按官網說法被依賴對象它應該是必須一個可以調用的對象比如:類,函數之類的···

這里看一下以類的形式:

import uvicorn
from fastapi import Depends, FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]

class CommonQueryParams:
    def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    response = {}
    # 如果q存在
    if commons.q:
        # 我們就把q加到一個新字典
        response.update({"q": commons.q})
        response.update({"小鍾": '同學'})
    # 然后在我們的fake_items_db進行截取
    items = fake_items_db[commons.skip: commons.skip + commons.limit]
    response.update({"items": items})
    return response

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

上面我們的CommonQueryParams是一個類,它和我的函數其實差不多,當我們的接口被調用的時候,類對象就回被初始化, 按官網的說法: commons: CommonQueryParams = Depends(CommonQueryParams) 和 commons = Depends(CommonQueryParams) 是等價的。 還有一種是: commons: CommonQueryParams = Depends()

示例運行演示

有Q參數:

http://127.0.0.1:8000/items/?q=2323

 

 

 

沒有Q參數:

http://127.0.0.1:8000/items/

 

多層嵌套依賴

多層嵌套的意思就是可以類可以類的意思。函數可以依賴函數。其實和我們的之前的參數校驗一樣。

比如下面的代碼:

import uvicorn
from fastapi import Cookie, Depends, FastAPI

app = FastAPI()

def query_extractor(q: str = None):
    return q

def query_or_cookie_extractor(
        q: str = Depends(query_extractor), last_query: str = Cookie(None)
):
    if not q:
        return last_query
    return q

@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
    return {"q_or_cookie": query_or_default}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

其實意思就是query_or_cookie_extractor 依賴於query_extractor,然后query_or_cookie_extractor被注入到接口上也被依賴的對象。

官網的截圖上面接口執行流程如下:

 

對於同一個依賴,如果處理的結果是一樣的,就是返回值是一樣的話,我們可以進行多次調用依賴,這時候可以對被依賴的對象設置是否使用緩存機制:

async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
  return {"fresh_value": fresh_value}

 

請求一下頁面

http://127.0.0.1:8000/items/

 

 由於沒有cookie,返回空

 

list列表依賴

我們先看官方提供的示例代碼:

import uvicorn
from fastapi import Depends, FastAPI, Header, HTTPException

app = FastAPI()

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")

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

@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

 

上述的代碼意思是對我們的請求頭部信息Header進行驗證,因為示例是...三個點,說明是必選的字段:

分析上述的代碼之后,運行一下試一試看看結果:

1:什么頭部參數都不傳遞的情況提示,我們的頭部參數異常

http://127.0.0.1:8000/items/

 

 

 

2:頭部參數填寫的情況:

注意點:參數提交的格式,因為是頭部的參數,所以我們的代碼上的x_token 會應該要寫:x-token才對

 

 

錯誤的示例:

 

 所以上面列表的依賴的意思就是必須兩天條件都成立才通過。這個感覺后期還是用到的比較多的喲!

 

多依賴對象注入和列表其實是一樣的:

import uvicorn

from fastapi import Depends, FastAPI, Header, HTTPException
from fastapi import Depends, FastAPI

app = FastAPI()

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")
    return 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

@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]

@app.get("/items2/")
async def items2(xt: str = Depends(verify_token), xk: str = Depends(verify_key)):
    return {"xt": xt, 'xk': xk}

if __name__ == '__main__':
    uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)

如上面的xt: str = Depends(verify_token),xk: str = Depends(verify_key),也是需要必須兩個條件成立才可以。

正常情況:

x-token=fake-super-secret-token
x-key=fake-super-secret-key

 

 

 

非正常情況:

x-token=fake-super-secret-token
x-key=fake-super-secret-key--fei

 

 

 

 

本文參考鏈接:

http://www.zyiz.net/tech/detail-119883.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM