想动态的给某函数或类添加功能, 而不改变原函数或类, 常用的方式就是使用python的装饰器,decorator, 对于做web的人来说, 装饰器用的最多的地方就是做权限设置

比如,该接口需要登录

from functools import wraps
def login_required(method):
    @wraps(method)
    def wrapper(self, *args, **kwargs):
        if not self.current_user:
            return self.write({"error": "login required"})
        return method(self, *args, **kwargs)
    return wrapper

class HelloWorldHandler(RequestHandler):
    @login_required
    def get(self):
        pass

这是最基础的做法。。。

如果要是想给装饰器传参, 比如, 这个接口你想给特定几种用户角色权限, 另一个接口是另一些用户角色(如: 采购人员和管理员可管理采购, 进货人员, 仓库管理员,管理员可管理进货。。。) 然后传的参数就是这些角色的列表, 这个实现起来也不难(这里就当管理员的role为1, 采购人员的role为2, 进货人员role为3, 仓库管理员的role为4)

from functools import wraps
def permission_required(role_list):
    def decorator(method):
        @wraps(method)
        def wrapper(self, *args, **kwargs):
            if not self.current_user:
                return self.write({'error': 'login required'})
            if not self.current_user['role'] in role_list:
                return self.write({'error': 'not permitted'})
            return method(self, *args, **kwargs)
        return wrapper
    return decorator

这个可以直接使用,像这样

class JinhuoHandler(RequestHandler):
    @permission_required(role_list=[1, 2])
    def post(self):
        pass

class JinhuoHandler(RequestHandler):
    @jinhuo_permission(role_list=[1, 3, 4])
    def post(self):
        pass 

或者想下面这种方式,这样应该更加推荐,修改起来也方便

def caigou_permission(method):
    return permission_required([1, 2])(method)

def jinhuo_permission(method):
    return permission_required([1, 3, 4])(method)
        
class CaigouHandler(RequestHandler):
    @caigou_permission
    def post(self):
        pass

class JinhuoHandler(RequestHandler):
    @jinhuo_permission
    def post(self):
        pass

三层闭包,还可以用curry方式(柯里话)缩一层掉 这里用了一个第三方库–toolz

from toolz import curry

@curry
def example(method, role_list):
    @wraps(method)
    def wrapper(self, *args, **kwargs):
        if not self.userid:
            return self.write(error(ErrorCode.LOGINERR))
        op = self.session['op']
        if op['role'] not in role_list:
            return self.write(error(ErrorCode.ROLEERR))
        return method(self, *args, **kwargs)
    return wrapper

class CaigouHandler(RequestHandler):
    @caigou_permission(role_list=[1, 2])
    def post(self):
        pass

class JinhuoHandler(RequestHandler):
    @jinhuo_permission(role_list=[1, 3, 4])
    def post(self):
        pass