繁体   English   中英

使用自定义路径参数将路由添加到 FastAPI

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM