因此,我需要在类中有一些路由,但是路由方法需要有self
属性(以访问类的属性)。然而,FastAPI假定self
是它自己的必需参数,并将其作为查询参数放入。
这是我得到的
app = FastAPI()
class Foo:
def __init__(y: int):
self.x = y
@app.get("/somewhere")
def bar(self): return self.x
但是,除非您转到/somewhere?self=something
,否则它将返回422
,问题是self
是str,因此没有用处。
我需要一些方法,使我仍然可以访问self
,而无需将其作为必需参数。
8条答案
按热度按时间yfjy0ee71#
这可以通过使用
APIRouter
的add_api_route
方法来完成:示例:
add_api_route
的第二个参数(endpoint
)具有类型Callable[..., Any]
,因此任何可调用项都应该工作(只要FastAPI可以找到如何解析其参数HTTP请求数据)。该可调用项在FastAPI文档中也称为路径操作函数(以下称为"POF")。为什么装饰方法不起作用
在类体中用
@app.get
和友元修饰方法是行不通的,因为你实际上是在传递Hello.hello
,而不是hello.hello
(也叫self.hello
)到add_api_route
。绑定和未绑定方法(也叫Python 3中的"函数")有不同的签名:FastAPI做了很多魔术,试图自动将HTTP请求中的数据(主体或查询参数)解析为POF实际使用的对象。
通过使用未绑定方法(=常规函数)(
Hello.hello
)作为POF,FastAPI必须:1.假设包含路径的类的性质并生成
self
(也称为Hello.__init__
),这可能会增加FastAPI的复杂性,这是FastAPI开发人员的一个用例(可以理解)似乎对支持不感兴趣。这似乎是处理应用程序/资源状态将整个问题推迟到具有Depends
的外部依赖性。1.从调用者发送的HTTP请求数据(通常是JSON)生成
self
对象,这在技术上对于字符串或其他内置函数之外的任何东西都是不可行的,因此实际上并不实用。OP代码中发生的事情是#2。FastAPI尝试从HTTP请求查询参数中解析
Hello.hello
(=self
,类型为Hello
)的第一个参数,显然失败并引发RequestValidationError
,该参数作为HTTP 422响应显示给调用者。从查询参数解析
self
为了证明上面的第2条,下面是一个(无用的)示例,说明FastAPI何时可以从HTTP请求中"解析"
self
:(* 免责声明:请勿将以下代码用于任何实际应用程序 *)
示例:
pobjuy322#
为了创建基于类的视图,你可以使用fastapi-utils中的@cbv decorator。
停止在相关端点的签名中一遍又一遍地重复相同的依赖关系。
您的示例可以重写如下:
ikfrs5lh3#
我不喜欢这样做的标准方式,所以我写了自己的库。你可以像这样安装它:
下面是如何使用它的示例:
注意,你不需要在每个方法周围都 Package 装饰器,根据它们在HTTP协议中的用途来命名方法就足够了,整个类都变成了一个装饰器。
mcvgt66p4#
我把路由放到
def __init__
,它工作正常,例如:ztigrdn85#
我刚刚发布了一个项目,它允许你使用一个类示例来进行简单装饰器的路由处理。
cbv
很酷,但是路由是在类本身上,而不是类的示例上。能够使用类示例让你以一种我感觉更简单和直观的方式进行依赖注入。例如,下面的代码按预期工作:
您可以find it on PyPi并通过
pip install classy-fastapi
进行安装。jdzmm42g6#
在这种情况下,我可以使用python类连接控制器,并使用一个协作者通过dep注入传递它。
Here full example plus tests
gv8xihay7#
另一种方法是使用decorator class that takes parameters,路由在之前注册并在运行时添加:
定义继承
APIRouter
的自定义路由器,并在__init__
处添加路由:nkhmeac68#
在类中继承FastAPI,并使用FastAPI装饰器作为方法调用(我将使用
APIRouter
演示它,但您的示例应该可以正常工作):