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

如何将FastAPI应用根路由拆分到独立文件并避免路径报错

解决FastAPI根路由拆分到独立文件的路径冲突问题

问题背景

尝试将网站根路由拆分到独立的website.py文件实现解耦时,频繁触发FastAPIError: Prefix and path cannot be both empty (path operation: root)错误,即使设置前缀为''或'/'也无法解决。目标是通过app.include_router(website.router)让根路由正常指向website.py,替代main.py中当前可正常运行的根路由代码。

错误原因

在APIRouter中定义了空字符串路径'',同时使用include_router时未指定前缀(或前缀为空),导致FastAPI检测到路径组合冲突——前缀和路径同时为空是不允许的。

解决方案

1. 修正website.py中的路由定义

删除空路径的装饰器@router.get('', include_in_schema=False),仅保留@router.get("/");或者将空路径改为'/',避免和空前缀冲突。

2. 调整main.py中的路由引入

取消website模块的导入注释,取消app.include_router(website.router)的注释,无需额外指定前缀(默认前缀为空即可匹配根路径)。

修改后的代码

main.py

from datetime import datetime, timedelta, timezone

from fastapi import FastAPI, Request, Depends, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

from asgi_csrf import asgi_csrf

from routers import signup, users, website  # 取消website的导入注释

templates = Jinja2Templates(directory="templates")

app = FastAPI(
    root_path="/dev"
)

app.mount("/static", StaticFiles(directory="static"), name="static")

# 原根路由代码已移至website.py,此处注释或删除
# @app.get('', include_in_schema=False)
# @app.get("/")
# async def root(request: Request, id: str = ""):
#     response = templates.TemplateResponse(
#         request=request, name="index.html", context={"id": id}
#     )
#     return response  

app.include_router(website.router)  # 取消该注释
app.include_router(signup.router, prefix="/signup")
app.include_router(users.router, prefix="/users")

website.py

from datetime import datetime, timedelta, timezone
import uuid

from typing import Annotated
from fastapi import APIRouter, Request, Cookie, Header, Depends, Form
from fastapi.templating import Jinja2Templates

from pydantic import BaseModel

router = APIRouter()

templates = Jinja2Templates(directory="templates")

# 仅保留一个根路径装饰器,删除空字符串路径的定义
@router.get("/")
async def root(request: Request, id: str = ""):
    response = templates.TemplateResponse(
        request=request, name="index.html", context={"id": id}
    )
    return response  

如果需要保留include_in_schema=False的配置,也可以写成:

@router.get("/", include_in_schema=False)
@router.get("/")
async def root(request: Request, id: str = ""):
    # ... 原有代码

这样既保留了schema隐藏的逻辑,又避免了空路径冲突。

内容的提问来源于stack exchange,提问作者Johnny John Boy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:27:23