高度な依存関係¶
パラメータ化された依存関係¶
これまで見てきた依存関係はすべて、固定された関数またはクラスでした。
しかし、多くの異なる関数やクラスを宣言することなく、依存関係にパラメータを設定したい場合があります。
クエリパラメータq
に特定の固定コンテンツが含まれているかどうかをチェックする依存関係があると想像してみましょう。
しかし、その固定コンテンツをパラメータ化できるようにしたいのです。
"呼び出し可能"なインスタンス¶
Pythonには、クラスのインスタンスを「呼び出し可能」にする方法があります。
クラス自体(これはすでに呼び出し可能)ではなく、そのクラスのインスタンスです。
それを行うには、__call__
メソッドを宣言します
from typing import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
🤓 その他のバージョンとバリアント
from fastapi import Depends, FastAPI
from typing_extensions import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
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 typing import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
🤓 その他のバージョンとバリアント
from fastapi import Depends, FastAPI
from typing_extensions import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
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 typing import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
🤓 その他のバージョンとバリアント
from fastapi import Depends, FastAPI
from typing_extensions import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
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}
このようにして、依存関係を「パラメータ化」することができ、属性checker.fixed_content
として、その中に"bar"
が含まれるようになります。
インスタンスを依存関係として使用する¶
次に、Depends(FixedContentQueryChecker)
の代わりに、Depends(checker)
でこのchecker
を使用できます。なぜなら、依存関係はクラス自体ではなく、インスタンスであるchecker
だからです。
そして、依存関係を解決するとき、FastAPIはこのchecker
を次のように呼び出します。
checker(q="somequery")
...そして、それが返す値を、パス操作関数の依存関係の値として、パラメータfixed_content_included
に渡します。
from typing import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
🤓 その他のバージョンとバリアント
from fastapi import Depends, FastAPI
from typing_extensions import Annotated
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: Annotated[bool, Depends(checker)]):
return {"fixed_content_in_query": fixed_content_included}
ヒント
可能であれば`Annotated`バージョンを使用することをお勧めします。
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}
ヒント
これらすべては不自然に思えるかもしれません。そして、それがまだどのように役立つかはあまり明確ではないかもしれません。
これらの例は意図的に単純ですが、すべてがどのように機能するかを示しています。
セキュリティに関する章では、同じ方法で実装されているユーティリティ関数があります。
これらすべてを理解していれば、セキュリティのためのユーティリティツールがどのように機能するかの裏側をすでに知っています。