FastApi(自用脚手架)+Snowy搭建后台管理系统(11)- 使用装饰器方式注入类形式依赖项

语言: CN / TW / HK

highlight: agate

前言

之前在定义我们的逻辑处理的时候,我个人是通过定义类的方式来处理,如下的代码所示:

@get(path='/b/getPicCaptchanew/', summary="你好")
async def getPicCaptcha(self, controller: IBaseController = Depends(GetPicCaptchaController)):
    '''
    ASDHJASHJDAH
    :return:
    '''

    return await controller.async_response()

@post("/b/doLogin2/", name='AAAAAAAAAAAAAAAAAAAA', summary='执行登入接口')
async def doLogin(self, controller: IBaseController = Depends(DoLoginController)):
    '''
     输入账号登入
    :param request:
    :return:
    '''
    return await controller.async_response()

在上面的代码中,我们是通过 Depends(DoLoginController)的方式实现我们定义的类实现的,其中DoLoginController的代码如下所示:

``` from fastapi import Request, Depends from sqlalchemy.ext.asyncio import AsyncSession from afast_core.core_plugins.db.sqlalchemy import async_session_class_v2_dependency from afast_core.core_tools.jwt_helper import SimpleAuth from snowy_src.snowy_common.snowy_controller.decorater import wrapper_record_background_task from snowy_src.snowy_common.snowy_errors.enums import SnowySystemResultEnum from snowy_src.snowy_common.snowy_errors.exception import SnowyBusinessException from snowy_src.snowy_system.snowy_modules.auth.controllers.base import IAuthIBaseController from snowy_src.snowy_system.snowy_modules.auth.enums import SaClientTypeEnum from snowy_src.snowy_system.snowy_modules.auth.repository.user import SysUserCRUDRepository from snowy_src.snowy_system.snowy_modules.auth.schemas import AuthAccountPasswordLoginParam

class IDoLoginControllerBaseController(IAuthIBaseController): ''' 定制相关约束检测函数逻辑步序 ''' pass

class IDoLoginController(IDoLoginControllerBaseController): ''' 定制相关约束检测函数逻辑步序 '''

def __init__(self, *, request: Request,
             async_session: AsyncSession = Depends(async_session_class_v2_dependency),
             schema_param: AuthAccountPasswordLoginParam,
             ):
    super().__init__(request=request, async_session=async_session)
    # 入参参数
    self.schema_param = schema_param
    self.sysuser_repo = SysUserCRUDRepository(self.async_session)
    self.userinfo = None

class DoLoginController(IDoLoginController):

# @wrapper_record_background_task
async def business_login(self):
    # 把相关业务逻辑分到authService服务中处理
    # return await self.authService.doLogin(self.schema_param, SaClientTypeEnum.B.value)
    return await self.doLogin()

async def doLogin(self):
    '''
    账号密码登录
    :param schema: 账号密码登入模型对象
    :param type:  指定用户登入的类型
    :return:

```

在上面的代码中,其实我们的对于在路由中使用如下代码所示: @post("/b/doLogin2/", name='AAAAAAAAAAAAAAAAAAAA', summary='执行登入接口') async def doLogin(self, controller: IBaseController = Depends(DoLoginController)): 感觉起来不是非常优雅,所以接下来的打算还是,想着能不能使用装饰器的注入类,然后注解的加到路由上即可,如下所示: @post("/b/doLogin2/", name='AAAAAAAAAAAAAAAAAAAA', summary='执行登入接口') async def doLogin(self, controller: DoLoginController): ''' 输入账号登入 :param request: :return: ''' return await controller.async_response()

实现思路

首先我们需要明确一点依赖项必须是一个可调用的对象,所以我们需要注意这点,所以我们的可以首先定义装饰器,如下代码所示:

def RestControllerWithDepends(*args, **kwargs): def back(cls): return Depends(cls(*args, **kwargs)) return back

该装饰器接收相关类可以传入的参数信息。然后定义具体被上面装饰器的依赖项类,如下: ```

@RestControllerWithDepends() class DoLoginController: def init(self): pass

def __call__(self):
    return "你好,我是没有参数被当做依赖项的类"

@RestControllerWithDepends(content='你是说我是谁呢?') class DoLoginController2: def init(self, content: str): self._content = content

def __call__(self):
    return "你好,我是一个有参数被当做依赖项的类" + self._content

```

到此为止,我们的就完整相关使用装饰器装饰某一个类为一个依赖处理。最后我们的把该类直接的写入路由上,如下代码所示: ```

@app.get('/1') def login1(test: str = DoLoginController): return "test:001" + test

@app.get('/2') def login2(test: str = DoLoginController2): return "test:002" + test ```

然后我们就可以实现类似 使用装饰器方式注入类形式依赖项的功能了。但是上面有一种情况就是假如我的类不是一个可调用对象,也就是说我类没有 call(self):函数,那么我的装饰器那种写法就有问题,比如下面的写法: ``` def RestControllerWithDepends(args, kwargs): def back(cls): return Depends(cls(args, **kwargs)) return back

@RestControllerWithDepends() class DoLoginController: pass ``` 会直接的爆出错误信息如下所示:

image.png 所以我们需要做相关的判断处理,但是你仔细想想如果一个类没有任何参数的话,好像也没有必要定义成为这种依赖项的形式了,所以暂时不考虑如上类的定义方式,如果非要实现的话,其实没有意义,因为一个依赖项一般都需要对应处理返回结果,但是上面那方式没有返回结果,所以感觉没必要!如果非必要的,只能判断被装饰器的类是不是一个可调用的对象,修改装饰为如下的形式: def RestControllerWithDepends(): def back(cls): return Depends(cls) return back 不过感觉没必要!这个看个人需求了! 至此,关于【实现 使用装饰器方式注入类形式依赖项】相关介绍分享已完成!以上内容分享纯属个人经验,仅供参考!

文笔有限,如有笔误或错误!欢迎批评指正!感谢各位大佬!有什么问题也可以随时交流!

结尾

END

简书:https://www.jianshu.com/u/d6960089b087

掘金:https://juejin.cn/user/2963939079225608

公众号:微信搜【程序员小钟同学】

新开QQ群号,欢迎随时加群交流,相互学习。QQ群号:247491107

小钟同学 | 文 【欢迎一起学习交流】| QQ:308711822