You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI路径参数模块化依赖引发422 Unprocessable Entity错误

FastAPI路径参数模块化依赖触发422 Unprocessable Entity错误

尝试为FastAPI路径参数创建模块化依赖时,持续触发422错误,相关代码如下:

from typing import Annotated, Any, Callable
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, Path

router = APIRouter()

def get_uuid_parameter(title: str, id_alias: str = 'id', id_description: str = "") -> Callable:
    def dependency(
            this_id: Annotated[str, Path(
                title=title,
                alias=id_alias,
                description=id_description,
                min_length=36,
                max_length=36,
            )]
        ) -> str:
        try:
            return str(UUID(this_id))
        except ValueError as e:
            raise HTTPException(status_code=400, detail=f"Invalid {title} format") from e
    return dependency


LocationIdDependency = Annotated[str, Depends(get_uuid_parameter(
    title="Location ID",
    id_alias='locationId',
    id_description="Location identifier",
    ))]


@router.get('/{location_id}')
async def get_location(location_id: LocationIdDependency) -> Any:
    return location_id

返回的错误信息如下:

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "path",
        "locationId"
      ],
      "msg": "Field required",
      "input": null
    }
  ]
}

使用Swagger UI和浏览器测试均出现该问题,但相同风格的查询参数依赖可以正常运行,代码示例如下:

# query_parameters.py
def get_date_parameter(title: str, alias: str = 'date', default: date | None = None) -> Callable:
    def dependency(
            date_param: Annotated[date | None, Query(
                alias=alias,
                title=title,
                description="Date in format YYYY-MM-DD",
                examples=['2022-12-31', '1970-01-01'],
            )] = None
        ) -> date | None:
        return date_param if date_param is not None else default
    return dependency


# dependencies.py
DateFromDependency = Annotated[date, Depends(
    get_date_parameter(title="From date", alias='dateFrom', default=date.today()))]
DateToDependency = Annotated[date | None, Depends(
    get_date_parameter(title="To date", alias='dateTo'))]


# calendar_router.py
@router.get('/')
async def get_calendar(session: DatabaseSessionDependency,
                            date_from: DateFromDependency,
                            date_to: DateToDependency,
                    ) -> Any:
# some code

问题原因

核心问题出在路径参数的alias设置上:

  • FastAPI中,路径参数的匹配逻辑是基于路由占位符(如/{location_id}中的location_id)与参数名称的严格一致性,alias参数在这里不起作用,反而会误导FastAPI去寻找名为locationId的路径参数,但路由里定义的是location_id,两者不匹配,因此抛出"Field required"错误。
  • 查询参数能正常工作是因为查询参数的alias用于映射URL中的查询键名,与函数参数名可以不一致;但路径参数依赖路由占位符传递值,必须保证参数名称与占位符完全对应。

修复方案

方案1:移除Path中的alias,统一参数名与路由占位符

修改get_uuid_parameter函数,去掉alias参数,并将依赖内的参数名改为与路由占位符一致的location_id:

def get_uuid_parameter(title: str, id_description: str = "") -> Callable:
    def dependency(
            location_id: Annotated[str, Path(
                title=title,
                description=id_description,
                min_length=36,
                max_length=36,
            )]
        ) -> str:
        try:
            return str(UUID(location_id))
        except ValueError as e:
            raise HTTPException(status_code=400, detail=f"Invalid {title} format") from e
    return dependency


LocationIdDependency = Annotated[str, Depends(get_uuid_parameter(
    title="Location ID",
    id_description="Location identifier",
    ))]


@router.get('/{location_id}')
async def get_location(location_id: LocationIdDependency) -> Any:
    return location_id

方案2:调整路由占位符与alias一致(不推荐,不符合Python变量命名规范)

如果一定要保留alias,可以将路由占位符改为{locationId},但Python函数参数名不允许大写字母,因此需要调整路由定义:

# 依赖函数保留alias设置
def get_uuid_parameter(title: str, id_alias: str = 'id', id_description: str = "") -> Callable:
    def dependency(
            this_id: Annotated[str, Path(
                title=title,
                alias=id_alias,
                description=id_description,
                min_length=36,
                max_length=36,
            )]
        ) -> str:
        try:
            return str(UUID(this_id))
        except ValueError as e:
            raise HTTPException(status_code=400, detail=f"Invalid {title} format") from e
    return dependency


LocationIdDependency = Annotated[str, Depends(get_uuid_parameter(
    title="Location ID",
    id_alias='locationId',
    id_description="Location identifier",
    ))]


# 路由占位符改为locationId
@router.get('/{locationId}')
async def get_location(location_id: LocationIdDependency) -> Any:
    return location_id

推荐使用方案1,符合Python命名规范,逻辑更清晰。

内容的提问来源于stack exchange,提问作者Dimitris Dermanis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:37:02