动态设置可选端点参数
Set an optional endpoint parameter dynamically
动态设置可选端点参数的最佳方法是什么?
我天真地尝试过 activated_on: Optional[date] = Depends(date.today)
认为 FastAPI 会调用可调用对象,但它不起作用。
@router.get("/dummy/path")
async def ep_name(
*,
db: Session = Depends(deps.get_db),
activated_on: Optional[date] = None,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
if activated_on is None: # the lines I would like to remove
activated_on = date.today() # and have it set by FastAPI instead
TL;DR
将 Depends
的可调用对象更改为辅助函数,并将可选值注入辅助函数而不是路由函数。这与您的代码的作用相同,只是现在您可以根据需要在任意多条路线中重复使用它。
为什么反之无效
不幸的是,activated_on: Optional[date] = Depends(date.today)
将无法工作,原因有二。
首先,如果您只想在 activated_on
未作为查询字符串传递的情况下调用依赖项,那是行不通的。 Depends
将意味着参数填充了可调用对象的响应,它将忽略您的参数名称 activated_on
恰好是传入的查询字符串的名称这一事实。基本上它会调用可调用对象(date.today
) 每次。
其次,在这种特殊情况下,实际上它不会调用 date.today
,因为当您声明依赖项时,DI 框架会尝试检查函数签名(通过 inspect
)。对于这个特定的可调用 date.today
它不能(我保证这是来自 datetime
顺便说一句)。造成这种情况的原因有几个,说实话,我并没有完全弄清楚为什么 today
会出现这种情况,但我认为它是在 python 之外调用一个函数,所以它无法检查它以确定函数的签名。我对这里的原因可能是错误的,但无论哪种方式你都不能将该函数用作依赖项。
解决方案
你可以使用一个小的辅助函数(依赖)_activated_on
作为你的依赖:
from typing import Optional
from datetime import date
from fastapi import FastAPI, Depends, Query
async def _activated_on(q: Optional[date] = Query(None, alias="activated_on")):
return q if q is not None else date.today()
@app.get("/dummy/path")
async def ep_name(activated_on: date = Depends(_activated_on)):
return f"activated_on: {activated_on}"
您的路由将处理以下情况:
情况 1:用户传递有效日期
例如https://example.com/dummy/path?activated_on=2021-12-25
当你调用你的路由时,如果你传入一个查询字符串“activated_on”,那么它会被传递到 _activated_on
函数中(在被 pydantic 解析为日期之后)然后用于注入您路线的 activated_on
arg。你可以只做辅助函数:
async def _activated_on(activated_on: Optional[date] = None):
return activated_on if activated_on is not None else date.today()
但是您的变量名称与您的路线相同,这可能会让人有些困惑。两个版本都做同样的事情,但感觉最不混乱的就做。
情况 2:用户未传递任何内容
例如https://example.com/dummy/path
q
将是 None
,因此辅助函数将调用 date.today()
和 return 将注入到 activated_on
arg 中的值你的路线。
案例 3:用户传递了无效日期
例如https://example.com/dummy/path?activated_on=2021-12-32
由于 pydantic 正在解析和验证查询字符串(如果存在),如果您提供的字符串无法解析为日期,则永远不会调用辅助函数,您将获得有用的错误响应。如果你想使用今天的日期,如果 activated_on
没有提供 或者 如果它提供但无效,你可以改变辅助函数中的类型提示从 date
到 str
然后自己进行转换,如果失败则回退到今天。
动态设置可选端点参数的最佳方法是什么?
我天真地尝试过 activated_on: Optional[date] = Depends(date.today)
认为 FastAPI 会调用可调用对象,但它不起作用。
@router.get("/dummy/path")
async def ep_name(
*,
db: Session = Depends(deps.get_db),
activated_on: Optional[date] = None,
current_user: models.User = Depends(deps.get_current_active_user),
) -> Any:
if activated_on is None: # the lines I would like to remove
activated_on = date.today() # and have it set by FastAPI instead
TL;DR
将 Depends
的可调用对象更改为辅助函数,并将可选值注入辅助函数而不是路由函数。这与您的代码的作用相同,只是现在您可以根据需要在任意多条路线中重复使用它。
为什么反之无效
不幸的是,activated_on: Optional[date] = Depends(date.today)
将无法工作,原因有二。
首先,如果您只想在 activated_on
未作为查询字符串传递的情况下调用依赖项,那是行不通的。 Depends
将意味着参数填充了可调用对象的响应,它将忽略您的参数名称 activated_on
恰好是传入的查询字符串的名称这一事实。基本上它会调用可调用对象(date.today
) 每次。
其次,在这种特殊情况下,实际上它不会调用 date.today
,因为当您声明依赖项时,DI 框架会尝试检查函数签名(通过 inspect
)。对于这个特定的可调用 date.today
它不能(我保证这是来自 datetime
顺便说一句)。造成这种情况的原因有几个,说实话,我并没有完全弄清楚为什么 today
会出现这种情况,但我认为它是在 python 之外调用一个函数,所以它无法检查它以确定函数的签名。我对这里的原因可能是错误的,但无论哪种方式你都不能将该函数用作依赖项。
解决方案
你可以使用一个小的辅助函数(依赖)_activated_on
作为你的依赖:
from typing import Optional
from datetime import date
from fastapi import FastAPI, Depends, Query
async def _activated_on(q: Optional[date] = Query(None, alias="activated_on")):
return q if q is not None else date.today()
@app.get("/dummy/path")
async def ep_name(activated_on: date = Depends(_activated_on)):
return f"activated_on: {activated_on}"
您的路由将处理以下情况:
情况 1:用户传递有效日期
例如https://example.com/dummy/path?activated_on=2021-12-25
当你调用你的路由时,如果你传入一个查询字符串“activated_on”,那么它会被传递到 _activated_on
函数中(在被 pydantic 解析为日期之后)然后用于注入您路线的 activated_on
arg。你可以只做辅助函数:
async def _activated_on(activated_on: Optional[date] = None):
return activated_on if activated_on is not None else date.today()
但是您的变量名称与您的路线相同,这可能会让人有些困惑。两个版本都做同样的事情,但感觉最不混乱的就做。
情况 2:用户未传递任何内容
例如https://example.com/dummy/path
q
将是 None
,因此辅助函数将调用 date.today()
和 return 将注入到 activated_on
arg 中的值你的路线。
案例 3:用户传递了无效日期
例如https://example.com/dummy/path?activated_on=2021-12-32
由于 pydantic 正在解析和验证查询字符串(如果存在),如果您提供的字符串无法解析为日期,则永远不会调用辅助函数,您将获得有用的错误响应。如果你想使用今天的日期,如果 activated_on
没有提供 或者 如果它提供但无效,你可以改变辅助函数中的类型提示从 date
到 str
然后自己进行转换,如果失败则回退到今天。