亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在類中使用 FastAPI 創建路由

如何在類中使用 FastAPI 創建路由

慕蓋茨4494581 2023-07-27 17:55:09
所以我需要在類中擁有一些路由,但路由方法需要具有 attr self(以訪問類的屬性)。然而,FastAPI 然后假設self是它自己的必需參數并將其作為查詢參數放入這就是我所擁有的:app = FastAPI()class Foo:    def __init__(y: int):        self.x = y    @app.get("/somewhere")    def bar(self): return self.x但是,422除非您轉到 ,否則該命令將會返回/somewhere?self=something。問題在于,這是selfstr,因此毫無用處。我需要一些我仍然可以訪問的方法,self而無需將其作為必需參數。
查看完整描述

5 回答

?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

APIRouter這可以通過使用 an的方法來完成add_api_route:


from fastapi import FastAPI, APIRouter



class Hello:


    def __init__(self, name: str):

        self.name = name

        self.router = APIRouter()

        self.router.add_api_route("/hello", self.hello, methods=["GET"])


    def hello(self):

        return {"Hello": self.name}



app = FastAPI()

hello = Hello("World")

app.include_router(hello.router)


例子:


$ curl 127.0.0.1:5000/hello

{"Hello":"World"}

add_api_route的第二個參數 ( endpoint) 具有 type Callable[..., Any],因此任何可調用都應該可以工作(只要 FastAPI 可以找到如何解析其參數 HTTP 請求數據)。此可調用函數在 FastAPI 文檔中也稱為路徑操作函數(下面稱為“POF”)。


為什么裝飾方法不起作用

警告:如果您對OP答案中的代碼不起作用的技術解釋不感興趣,請忽略此答案的其余部分


在類主體中使用 and 朋友裝飾方法@app.get是行不通的,因為您將有效地傳遞Hello.hello,而不是hello.hello(又名self.hello)到add_api_route。綁定和非綁定方法(自 Python 3 起簡稱為“函數” )具有不同的簽名:


import inspect

inspect.signature(Hello.hello)  # <Signature (self)>

inspect.signature(hello.hello)  # <Signature ()>

FastAPI 做了很多魔法來嘗試自動將 HTTP 請求中的數據(正文或查詢參數)解析為 POF 實際使用的對象。


通過使用未綁定方法(=常規函數)( Hello.hello) 作為 POF,FastAPI 必須:


對包含路由的類的性質做出假設并動態生成self(也稱為調用Hello.__init__)。這可能會給 FastAPI 增加很多復雜性,并且 FastAPI 開發人員(可以理解)似乎對支持這個用例不感興趣。處理應用程序/資源狀態的推薦方法似乎是將整個問題推遲到Depends.


以某種方式能夠self從調用者發送的 HTTP 請求數據(通常是 JSON)生成對象。這在技術上對于字符串或其他內置函數之外的任何東西都是不可行的,因此實際上不可用。


OP 代碼中發生的情況是#2。FastAPI 嘗試從 HTTP 請求查詢參數中解析Hello.hello(= self,類型) 的第一個參數,顯然失敗并引發,該參數作為 HTTP 422 響應顯示給調用者。HelloRequestValidationError


self從查詢參數解析

只是為了證明上面的#2,這里有一個(無用的)示例,說明 FastAPI 何時可以真正self從 HTTP 請求中“解析”:


(免責聲明:請勿將以下代碼用于任何實際應用)

from fastapi import FastAPI


app = FastAPI()


class Hello(str):

    @app.get("/hello")

    def hello(self):

        return {"Hello": self}

例子:


$ curl '127.0.0.1:5000/hello?self=World'

{"Hello":"World"}


查看完整回答
反對 回復 2023-07-27
?
30秒到達戰場

TA貢獻1828條經驗 獲得超6個贊

要創建基于類的視圖,您可以使用fastapi-utils中的@cbv裝飾器。使用它的動機:

停止在相關端點的簽名中一遍又一遍地重復相同的依賴關系。

您的示例可以這樣重寫:

from fastapi import Depends, FastAPI

from fastapi_utils.cbv import cbv

from fastapi_utils.inferring_router import InferringRouter



def get_x():

? ? return 10



app = FastAPI()

router = InferringRouter()? # Step 1: Create a router



@cbv(router)? # Step 2: Create and decorate a class to hold the endpoints

class Foo:

? ? # Step 3: Add dependencies as class attributes

? ? x: int = Depends(get_x)


? ? @router.get("/somewhere")

? ? def bar(self) -> int:

? ? ? ? # Step 4: Use `self.<dependency_name>` to access shared dependencies

? ? ? ? return self.x



app.include_router(router)


查看完整回答
反對 回復 2023-07-27
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

我不喜歡這樣做的標準方法,所以我編寫了自己的庫。你可以像這樣安裝它:


$ pip install cbfa

以下是如何使用它的示例:


from typing import Optional

from fastapi import FastAPI

from pydantic import BaseModel

from cbfa import ClassBased



app = FastAPI()

wrapper = ClassBased(app)


class Item(BaseModel):

    name: str

    price: float

    is_offer: Optional[bool] = None


@wrapper('/item')

class Item:

    def get(item_id: int, q: Optional[str] = None):

        return {"item_id": item_id, "q": q}


    def post(item_id: int, item: Item):

        return {"item_name": item.name, "item_id": item_id}

請注意,您不需要在每個方法周圍包裝裝飾器。根據方法在 HTTP 協議中的用途來命名這些方法就足夠了。整個類都變成了一個裝飾器。


查看完整回答
反對 回復 2023-07-27
?
慕沐林林

TA貢獻2016條經驗 獲得超9個贊

我把路線放到def __init__. 它工作正常。例子:


from fastapi import FastAPI

from fastapi.responses import HTMLResponse


class CustomAPI(FastAPI):

    def __init__(self, title: str = "CustomAPI") -> None:

        super().__init__(title=title)


        @self.get('/')

        async def home():

            """

            Home page

            """

            return HTMLResponse("<h1>CustomAPI</h1><br/><a href='/docs'>Try api now!</a>", status_code=status.HTTP_200_OK)



查看完整回答
反對 回復 2023-07-27
?
喵喔喔

TA貢獻1735條經驗 獲得超5個贊

我剛剛發布了一個項目,允許您使用類實例通過簡單的裝飾器進行路由處理。cbv很酷,但路由是在類本身上,而不是類的實例上。能夠使用類實例可以讓您以一種對我來說更簡單、更直觀的方式進行依賴項注入。


例如,以下內容按預期工作:


from classy_fastapi import Routable, get, delete


class UserRoutes(Routable):

? ?"""Inherits from Routable."""


? ?# Note injection here by simply passing values

? ?# to the constructor. Other injection frameworks also?

? ?# supported as there's nothing special about this __init__ method.

? ?def __init__(self, dao: Dao) -> None:

? ? ? """Constructor. The Dao is injected here."""

? ? ? super().__init__()

? ? ? self.__dao = Dao


? ?@get('/user/{name}')

? ?def get_user_by_name(name: str) -> User:

? ? ? # Use our injected DAO instance.

? ? ? return self.__dao.get_user_by_name(name)


? ?@delete('/user/{name}')

? ?def delete_user(name: str) -> None:

? ? ? self.__dao.delete(name)



def main():

? ? args = parse_args()

? ? # Configure the DAO per command line arguments

? ? dao = Dao(args.url, args.user, args.password)

? ? # Simple intuitive injection

? ? user_routes = UserRoutes(dao)

? ??

? ? app = FastAPI()

? ? # router member inherited from Routable and configured per the annotations.

? ? app.include_router(user_routes.router)

您可以在 PyPi 上找到它并通過 進行安裝pip install classy-fastapi



查看完整回答
反對 回復 2023-07-27
  • 5 回答
  • 0 關注
  • 686 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號