动态设置可选端点参数的最佳方法是什么?
天真地,我尝试过 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
的可调用更改为辅助函数,并将可选值注入(inject)辅助函数而不是路由函数中。这与您的代码执行相同的操作,只不过现在您可以在任意数量的路由中重用它。
为什么它不能以其他方式工作
不幸的是,activated_on:Optional[date] = Depends(date.today)
由于两个原因不起作用。
首先,如果您只想在 activated_on
未作为查询字符串传递时调用可靠的方法,那么这是行不通的。 Depends
意味着参数由可调用的响应填充,它将忽略您的参数名称 activated_on
恰好是传入的查询字符串的名称这一事实。基本上它每次都会调用可调用的(date.today
)。
其次,在这种特殊情况下,实际上它不会调用 date.today
因为当您声明依赖项时,DI 框架会尝试检查函数签名(通过 inspect
>)。对于这个特定的可调用date.today
,它不能(顺便说一句,我假设这是来自datetime
)。造成这种情况的原因有几个,老实说,我并没有完全弄清楚为什么今天会出现这种情况,但我认为它正在调用 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解析为日期之后),然后用于注入(inject)到您的路线的 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()
并返回该值,该值将被注入(inject)路线的 activated_on
参数。
情况 3:用户传递无效日期
例如https://example.com/dummy/path?activated_on=2021-12-32
由于 pydantic 正在解析和验证查询字符串(如果存在),因此如果您提供的字符串无法解析为日期,则辅助函数将永远不会被调用,并且您将获得有用的错误响应。如果您想在未提供 activated_on
的情况下使用今天的日期或者如果提供了但无效,则可以从 更改辅助函数中的类型提示date
到 str
然后自己进行转换,如果失败则回退到今天。
关于python - 动态设置可选端点参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68677907/