,," /> " />

目 录CONTENT

文章目录

装饰器-fastapi-1

Administrator
2024-04-26 / 0 评论 / 0 点赞 / 16 阅读 / 11645 字

fastapi

FastAPI中的路由是通过装饰器(Decorator)的方式来定义的

APIRouter允许你在不同的模块中定义路由操作,然后将它们挂载到全局应用程序路由中

from fastapi import APIRouter

router = APIRouter()

@router.get("/get")
async def get():
    return {'api': 'get'}
    
@router.post("/post")
async def post():
    return {'api': 'post'}
    
@router.put("/put")
async def put():
    return {'api': 'put'}
    
@router.patch("/patch")
async def patch():
    return {'api': 'patch'}
    
@router.delete("/delete")
async def delete():
    return {'api': 'delete'}

路由注册

from fastapi import FastAPI
from routers.router_1 import router

app = FastAPI()
app.include_router(router)
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello, World"}
  • @app.get("/") 是一个装饰器,它告诉 FastAPI 当收到 GET 请求并且 URL 路径为 "/" 时,调用下面定义的 read_root() 函数来处理请求
  • 装饰器的原理是在 FastAPI 内部维护一个路由表,将 URL 路径和请求方法与处理函数进行关联。当收到请求时,FastAPI 根据请求的 URL 和方法查找路由表,并调用对应的处理函数来处理请求
class APIRouter(routing.Router):
    def __init__(
        self,
        routes: List[routing.BaseRoute] = None,
        redirect_slashes: bool = True,
        default: ASGIApp = None,
        dependency_overrides_provider: Any = None,
        route_class: Type[APIRoute] = APIRoute,
        default_response_class: Type[Response] = None,
        on_startup: Sequence[Callable] = None,
        on_shutdown: Sequence[Callable] = None,
    ) -> None:
        super().__init__(
            routes=routes,
            redirect_slashes=redirect_slashes,
            default=default,
            on_startup=on_startup,
            on_shutdown=on_shutdown,
        )
        self.dependency_overrides_provider = dependency_overrides_provider
        self.route_class = route_class
        self.default_response_class = default_response_class
    def get(
        self,
        path: str,
        *,
        response_model: Type[Any] = None,
        status_code: int = 200,
        tags: List[str] = None,
        dependencies: Sequence[params.Depends] = None,
        summary: str = None,
        description: str = None,
        response_description: str = "Successful Response",
        responses: Dict[Union[int, str], Dict[str, Any]] = None,
        deprecated: bool = None,
        operation_id: str = None,
        response_model_include: Union[SetIntStr, DictIntStrAny] = None,
        response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
        response_model_by_alias: bool = True,
        response_model_skip_defaults: bool = None,
        response_model_exclude_unset: bool = False,
        response_model_exclude_defaults: bool = False,
        response_model_exclude_none: bool = False,
        include_in_schema: bool = True,
        response_class: Type[Response] = None,
        name: str = None,
        callbacks: List[APIRoute] = None,
    ) -> Callable:
        if response_model_skip_defaults is not None:
            warning_response_model_skip_defaults_deprecated()  # pragma: nocover
        return self.api_route(
            path=path,
            response_model=response_model,
            status_code=status_code,
            tags=tags or [],
            dependencies=dependencies,
            summary=summary,
            description=description,
            response_description=response_description,
            responses=responses or {},
            deprecated=deprecated,
            methods=["GET"],
            operation_id=operation_id,
            response_model_include=response_model_include,
            response_model_exclude=response_model_exclude,
            response_model_by_alias=response_model_by_alias,
            response_model_exclude_unset=bool(
                response_model_exclude_unset or response_model_skip_defaults
            ),
            response_model_exclude_defaults=response_model_exclude_defaults,
            response_model_exclude_none=response_model_exclude_none,
            include_in_schema=include_in_schema,
            response_class=response_class or self.default_response_class,
            name=name,
            callbacks=callbacks,
        )
def api_route(
        self,
        path: str,
        *,
        response_model: Type[Any] = None,
        status_code: int = 200,
        tags: List[str] = None,
        dependencies: Sequence[params.Depends] = None,
        summary: str = None,
        description: str = None,
        response_description: str = "Successful Response",
        responses: Dict[Union[int, str], Dict[str, Any]] = None,
        deprecated: bool = None,
        methods: List[str] = None,
        operation_id: str = None,
        response_model_include: Union[SetIntStr, DictIntStrAny] = None,
        response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
        response_model_by_alias: bool = True,
        response_model_skip_defaults: bool = None,
        response_model_exclude_unset: bool = False,
        response_model_exclude_defaults: bool = False,
        response_model_exclude_none: bool = False,
        include_in_schema: bool = True,
        response_class: Type[Response] = None,
        name: str = None,
        callbacks: List[APIRoute] = None,
    ) -> Callable:
        if response_model_skip_defaults is not None:
            warning_response_model_skip_defaults_deprecated()  # pragma: nocover

        def decorator(func: Callable) -> Callable:
            self.add_api_route(
                path,
                func,
                response_model=response_model,
                status_code=status_code,
                tags=tags or [],
                dependencies=dependencies,
                summary=summary,
                description=description,
                response_description=response_description,
                responses=responses or {},
                deprecated=deprecated,
                methods=methods,
                operation_id=operation_id,
                response_model_include=response_model_include,
                response_model_exclude=response_model_exclude,
                response_model_by_alias=response_model_by_alias,
                response_model_exclude_unset=bool(
                    response_model_exclude_unset or response_model_skip_defaults
                ),
                response_model_exclude_defaults=response_model_exclude_defaults,
                response_model_exclude_none=response_model_exclude_none,
                include_in_schema=include_in_schema,
                response_class=response_class or self.default_response_class,
                name=name,
                callbacks=callbacks,
            )
            return func

        return decorator
    def add_api_route(
        self,
        path: str,
        endpoint: Callable,
        *,
        response_model: Type[Any] = None,
        status_code: int = 200,
        tags: List[str] = None,
        dependencies: Sequence[params.Depends] = None,
        summary: str = None,
        description: str = None,
        response_description: str = "Successful Response",
        responses: Dict[Union[int, str], Dict[str, Any]] = None,
        deprecated: bool = None,
        methods: Optional[Union[Set[str], List[str]]] = None,
        operation_id: str = None,
        response_model_include: Union[SetIntStr, DictIntStrAny] = None,
        response_model_exclude: Union[SetIntStr, DictIntStrAny] = set(),
        response_model_by_alias: bool = True,
        response_model_skip_defaults: bool = None,
        response_model_exclude_unset: bool = False,
        response_model_exclude_defaults: bool = False,
        response_model_exclude_none: bool = False,
        include_in_schema: bool = True,
        response_class: Type[Response] = None,
        name: str = None,
        route_class_override: Optional[Type[APIRoute]] = None,
        callbacks: List[APIRoute] = None,
    ) -> None:
        if response_model_skip_defaults is not None:
            warning_response_model_skip_defaults_deprecated()  # pragma: nocover
        route_class = route_class_override or self.route_class
        route = route_class(
            path,
            endpoint=endpoint,
            response_model=response_model,
            status_code=status_code,
            tags=tags or [],
            dependencies=dependencies,
            summary=summary,
            description=description,
            response_description=response_description,
            responses=responses or {},
            deprecated=deprecated,
            methods=methods,
            operation_id=operation_id,
            response_model_include=response_model_include,
            response_model_exclude=response_model_exclude,
            response_model_by_alias=response_model_by_alias,
            response_model_exclude_unset=bool(
                response_model_exclude_unset or response_model_skip_defaults
            ),
            response_model_exclude_defaults=response_model_exclude_defaults,
            response_model_exclude_none=response_model_exclude_none,
            include_in_schema=include_in_schema,
            response_class=response_class or self.default_response_class,
            name=name,
            dependency_overrides_provider=self.dependency_overrides_provider,
            callbacks=callbacks,
        )
        self.routes.append(route)

自定义装饰器添加到FastAPI路由

from fastapi import Request, HTTPException
from fastapi import Request
from fastapi import APIRouter,Depends
from sqlalchemy.orm import Session
from app.api import deps

def custom_decorator(view_func):
    async def wrapper(request: Request):
        # 添加自定义逻辑
        # 例如,验证用户是否有权限访问该路由
        logger.info("用户验证访问路由")
        if not user_has_permission(request):
            logger.info("用户验证访问路由失败")
            raise HTTPException(status_code=403, detail="Forbidden")
        else:
            logger.info("用户验证访问路由通过")
        
        # 执行视图函数
        response = await view_func(request)
        
        # 添加自定义逻辑
        # 例如,记录日志
        # log_request(request, response)
        
        return response
    
    def user_has_permission(request: Request):
        # 实现用户权限验证逻辑
        # 例如,从请求中获取用户信息,并检查其权限
        return True  # 示例中始终返回 True,表示权限通过
    
    return wrapper

from fastapi import Request

router = APIRouter()
@router.get("/test")
@custom_decorator
async def test_fastapi_router(request: Request,db: Session = Depends(deps.get_db)):
    logger.info("测试函数执行结束")

# 执行结果
# 2024-04-26 10:11:26.043 | INFO     | app.api.api_v1.endpoints.platform.shangong.project:wrapper:43 - 用户验证访问路由
# 2024-04-26 10:11:26.043 | INFO     | app.api.api_v1.endpoints.platform.shangong.project:wrapper:48 - 用户验证访问路由通过
# 2024-04-26 10:11:26.043 | INFO     | app.api.api_v1.endpoints.platform.shangong.project:test_fastapi_router:72 - 测试函数执行结束

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区