问题描述
因此,我需要在一个类中包含一些路由,但是route方法需要具有self
attr(以访问该类的属性)。
但是,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
。问题在于self
是str,因此无用。
我需要某种方式,使我仍然可以访问self
而不必将其作为必需参数。
解决方法
要创建基于类的视图,可以使用@cbv中的fastapi-utils装饰器。使用它的动机:
停止在相关端点的签名中反复重复相同的依赖项。
您的示例可以这样重写:
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)
,
我不喜欢这样做的标准方式,所以我编写了自己的库。你可以这样安装:
$ 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 协议中的用途来命名方法就足够了。整个类都变成了装饰器。
,您从类中的FastAPI继承,并将FastAPI装饰器用作方法调用(我将使用APIRouter
进行显示,但您的示例应该可以运行):
class Foo(FastAPI):
def __init__(y: int):
self.x = y
self.include_router(
health.router,prefix="/api/v1/health",)
,
我将路由放到 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)