Подзависимости
Вы можете создавать зависимости, у которых есть подзависимости.
Их глубина может быть любой.
FastAPI позаботится об их разрешении.
Первая зависимость «зависимость»
Вы можете создать первую зависимость («зависимость») следующим образом:
from typing import Annotated
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: Annotated[str, Depends(query_extractor)],
last_query: Annotated[str | None, Cookie()] = None,
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(
query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
):
return {"q_or_cookie": query_or_default}
🤓 Другие версии и варианты
Совет
По возможности предпочтительно использовать версию Annotated.
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: str = Depends(query_extractor), last_query: str | None = Cookie(default=None)
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
return {"q_or_cookie": query_or_default}
Она объявляет необязательный параметр запроса q как str, а затем просто возвращает его.
Это довольно просто (и не очень полезно), но поможет нам разобраться, как работают подзависимости.
Вторая зависимость — «зависимость» и «зависимая зависимость»
Затем вы можете создать другую функцию-зависимость («зависимость»), которая одновременно объявляет собственную зависимость (то есть тоже является «зависимой»):
from typing import Annotated
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: Annotated[str, Depends(query_extractor)],
last_query: Annotated[str | None, Cookie()] = None,
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(
query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
):
return {"q_or_cookie": query_or_default}
🤓 Другие версии и варианты
Совет
По возможности предпочтительно использовать версию Annotated.
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: str = Depends(query_extractor), last_query: str | None = Cookie(default=None)
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
return {"q_or_cookie": query_or_default}
Рассмотрим объявленные параметры:
- Хотя эта функция сама является зависимостью («зависимостью»), она также объявляет другую зависимость (то есть «зависит» от чего-то ещё).
- Она зависит от
query_extractorи присваивает параметруqвозвращаемое ею значение.
- Она зависит от
- Она также объявляет необязательную cookie
last_queryтипаstr.- Если пользователь не указал параметр запроса
q, мы используем последний запрос, сохранив его ранее в cookie.
- Если пользователь не указал параметр запроса
Использование зависимости
Затем мы можем использовать зависимость следующим образом:
from typing import Annotated
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: Annotated[str, Depends(query_extractor)],
last_query: Annotated[str | None, Cookie()] = None,
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(
query_or_default: Annotated[str, Depends(query_or_cookie_extractor)],
):
return {"q_or_cookie": query_or_default}
🤓 Другие версии и варианты
Совет
По возможности предпочтительно использовать версию Annotated.
from fastapi import Cookie, Depends, FastAPI
app = FastAPI()
def query_extractor(q: str | None = None):
return q
def query_or_cookie_extractor(
q: str = Depends(query_extractor), last_query: str | None = Cookie(default=None)
):
if not q:
return last_query
return q
@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
return {"q_or_cookie": query_or_default}
Примечание
Обратите внимание: в функции операции пути мы объявляем только одну зависимость — query_or_cookie_extractor.
Но FastAPI поймёт, что сначала нужно разрешить query_extractor, чтобы передать его результаты в query_or_cookie_extractor при вызове этой функции.
graph TB query_extractor(["query_extractor"]) query_or_cookie_extractor(["query_or_cookie_extractor"]) read_query["/items/"] query_extractor --> query_or_cookie_extractor --> read_query
Многократное использование одной и той же зависимости
Если одна из ваших зависимостей объявлена несколько раз для одной и той же операции пути — например, если у нескольких зависимостей есть общая подзависимость, — FastAPI вызовет эту подзависимость только один раз для каждого запроса.
Возвращённое значение будет сохранено в «кэше» и передано всем «зависимым», которым оно требуется в рамках этого запроса, вместо многократного вызова зависимости для одного и того же запроса.
В более сложном сценарии, когда вам нужно, чтобы зависимость вызывалась на каждом шаге (возможно, несколько раз) в рамках одного запроса, а не использовалось «закэшированное» значение, при использовании Depends можно задать параметр use_cache=False:
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
return {"fresh_value": fresh_value}
Совет
По возможности предпочтительно использовать версию Annotated.
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {"fresh_value": fresh_value}
Итоги
Если не обращать внимания на все эти сложные термины, система внедрения зависимостей довольно проста.
Это просто функции, похожие на функции операций пути.
Но при этом она очень мощная и позволяет объявлять сколь угодно глубоко вложенные «графы» зависимостей (деревья).
Совет
В этих простых примерах всё это может показаться не очень полезным.
Но вы увидите, насколько это полезно, в главах о безопасности.
Вы также увидите, сколько кода это поможет вам сэкономить.
© 2018 Sebastián Ramírez
Licensed under the MIT License.
https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/