我们看到的所有依赖项都是一个固定的函数或类。
但是在某些情况下,您希望能够在依赖项上设置参数,而不必声明许多不同的函数或类。
假设我们想要一个依赖项来检查查询参数是否q包含某些固定内容。
但是我们希望能够参数化该固定内容。
在 Python 中,有一种方法可以使类的实例成为“可调用的”。
不是类本身(已经是可调用的),而是该类的实例。
为此,我们声明了一个方法__call__:
from fastapi import Depends, FastAPI
app = FastAPI()
class FixedContentQueryChecker:
def __init__(self, fixed_content: str):
self.fixed_content = fixed_content
def __call__(self, q: str = ""):
if q:
return self.fixed_content in q
return False
checker = FixedContentQueryChecker("bar")
@app.get("/query-checker/")
async def read_query_check(fixed_content_included: bool = Depends(checker)):
return {"fixed_content_in_query": fixed_content_included}
在这种情况下,这__call__就是FastAPI将用于检查附加参数和子依赖项的内容,并且稍后将调用此内容将值传递给您的路径操作函数中的参数。
现在,我们可以使用__init__来声明我们可以用来“参数化”依赖项的实例的参数:
from fastapi import Depends, FastAPI
app = FastAPI()
class FixedContentQueryChecker:
def __init__(self, fixed_content: str):
self.fixed_content = fixed_content
def __call__(self, q: str = ""):
if q:
return self.fixed_content in q
return False
checker = FixedContentQueryChecker("bar")
@app.get("/query-checker/")
async def read_query_check(fixed_content_included: bool = Depends(checker)):
return {"fixed_content_in_query": fixed_content_included}
在这种情况下,FastAPI永远不会触及或关心__init__,我们将直接在我们的代码中使用它。
我们可以使用以下命令创建此类的实例:
from fastapi import Depends, FastAPI
app = FastAPI()
class FixedContentQueryChecker:
def __init__(self, fixed_content: str):
self.fixed_content = fixed_content
def __call__(self, q: str = ""):
if q:
return self.fixed_content in q
return False
checker = FixedContentQueryChecker("bar")
@app.get("/query-checker/")
async def read_query_check(fixed_content_included: bool = Depends(checker)):
return {"fixed_content_in_query": fixed_content_included}
这样我们就可以“参数化”我们的依赖项,现在"bar"在它内部,作为属性checker.fixed_content。
然后,我们可以checker在Depends(checker), 而不是 中使用 this Depends(FixedContentQueryChecker),因为依赖项是实例checker,而不是类本身。
在解决依赖时,FastAPI会这样调用checker:
checker(q="somequery")
...并将在我们的路径操作函数中作为依赖值返回的任何内容作为参数传递fixed_content_included:
from fastapi import Depends, FastAPI
app = FastAPI()
class FixedContentQueryChecker:
def __init__(self, fixed_content: str):
self.fixed_content = fixed_content
def __call__(self, q: str = ""):
if q:
return self.fixed_content in q
return False
checker = FixedContentQueryChecker("bar")
@app.get("/query-checker/")
async def read_query_check(fixed_content_included: bool = Depends(checker)):
return {"fixed_content_in_query": fixed_content_included}
提示
这一切似乎都是人为的。可能还不是很清楚它有什么用处。
这些示例故意简单,但展示了它是如何工作的。
在有关安全性的章节中,有以相同方式实现的实用程序函数。
如果您理解了所有这些,您就已经知道这些用于安全性的实用工具在底层是如何工作的。