[英]Add route to FastAPI with custom path parameters
我正在尝试向 FastAPI 项目添加一些路由。 新路线不是事先确定的,代码应该从文件中读取它们。 要添加路线,我使用add_api_route
如下:
from fastapi import APIRouter
my_router = APIRouter()
def foo(xyz):
return {"Result": xyz}
my_router.add_api_route('/foo/{xyz}', endpoint=foo)
以上工作正常。
但是 enrty 路径参数不是固定的,我需要从文件中读取它们,为了实现这一点,我正在尝试这样的事情:
from fastapi import APIRouter
my_router = APIRouter()
def foo(**kwargs):
return {"Result": kwargs['xyz']}
read_from_file = '/foo/{xyz}' # Assume this is read from a file
my_router.add_api_route(read_from_file, endpoint=foo)
但它抛出了这个错误:
{"detail":[{"loc":["query","kwargs"],"msg":"field required","type":"value_error.missing"}]}
FastAPI 尝试在foo
签名中找到实际参数xyz
。
FastAPI 中有什么方法可以实现这一点吗? 甚至任何接受/foo/... whatever.../
?
这将生成一个带有新签名的 function(我假设每个参数都是一个字符串):
from fastapi import APIRouter
import re
import inspect
my_router = APIRouter()
def generate_function_signature(route_path: str):
args = {arg: str for arg in re.findall(r'\{(.*?)\}', route_path)}
def new_fn(**kwargs):
return {"Result": kwargs['xyz']}
params = [
inspect.Parameter(param,
inspect.Parameter.POSITIONAL_OR_KEYWORD,
annotation=type_)
for param, type_ in args.items()
]
new_fn.__signature__ = inspect.Signature(params)
new_fn.__annotations__ = args
return new_fn
read_from_file = '/foo/{xyz}' # Assume this is read from a file
my_router.add_api_route(read_from_file, endpoint=generate_function_signature(read_from_file))
read_from_file = '/foo/bar/{xyz}' # Assume this is read from a file
my_router.add_api_route(read_from_file, endpoint=generate_function_signature(read_from_file))
但是我确信有更好的方法来做你想做的任何事情,但我需要先了解你的问题
如此处所述,您可以使用Starlette提供的path
转换器来捕获任意路径。 如果您要将**kwargs
作为路径的一部分传递给您的路线,例如http://127.0.0.1:8000/foo/foo=2&bar=7
,那么您可以解析路径字符串并使用urllib.parse.parse_qs
,如this answer所示(类似于你会做的,如果你必须解析一个查询字符串)。 下面也使用这里描述的方法。 下面的例子:
from fastapi import APIRouter, FastAPI
from urllib.parse import parse_qs
app = FastAPI()
my_router = APIRouter()
def foo(full_path: str):
params = parse_qs(full_path)
d = dict( (k, v if len(v)>1 else v[0])
for k, v in params.items() )
return {"path": full_path, "params": d}
route_path = '/foo/{full_path:path}'
my_router.add_api_route(route_path, endpoint=foo)
app.include_router(my_router)
输入测试:
http://127.0.0.1:8000/foo/foo=2&bar=7&foo=10
Output:
{"path":"foo=2&bar=7&foo=10","params":{"foo":["2","10"],"bar":"7"}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.