Flask添加token_required装饰器后出现TypeError参数冲突问题求助
问题与分析
问题场景
开发多语言教育软件的Flask RESTful API时,遇到参数传递冲突错误:
- 未加装饰器的路由(正常运行):
@lessons_bp.route("/banner/<lang>", methods=["GET"]) def get_banner(lang):
- 添加
token_required装饰器后触发报错:
@lessons_bp.route("/banner/<lang>", methods=["GET"]) @token_required def get_banner(lang):
- 报错信息:
TypeError: get_banner() got multiple values for argument 'lang' - 临时规避方案:给函数增加一个dummy参数改为
def get_banner(self, lang):后恢复正常。
装饰器代码
def token_required(f): @wraps(f) def decorated(*args, **kwargs): token = None if "Authorization" in request.headers: token = request.headers["Authorization"] if not token: return make_response( {"message":"Access token required!"}, 401 ) try: data = jwt.decode(token, JWT_SECRET_KEY, ALGORITHM) current_user = User.query.filter_by(UserId = data["id"]).first() except Exception as e: print(e) return make_response( { "message": "Unable to verify token!" }, 401 ) return f(current_user, *args, **kwargs) return decorated
错误原因
Flask处理路由参数时,会把<lang>以关键字参数(即lang=xxx)的形式传入视图函数。而你的装饰器在调用原函数时,先传入current_user作为位置参数,再传递*args(此处为空)和**kwargs(包含lang的键值对)。
当视图函数定义为def get_banner(lang):时,装饰器的调用逻辑等价于get_banner(current_user, lang=xxx)——此时lang既被位置参数current_user占用,又通过关键字参数传入,直接导致参数重复赋值,触发got multiple values错误。
改成def get_banner(self, lang):时,current_user会被赋值给self参数,lang通过关键字参数正常接收,参数不再冲突,因此报错消失。
解决方案
有两种规范的修正方式:
方式1:调整视图函数签名
让视图函数直接接收current_user位置参数:
@lessons_bp.route("/banner/<lang>", methods=["GET"]) @token_required def get_banner(current_user, lang): # 业务逻辑代码
方式2:修改装饰器传参方式
将current_user以关键字参数形式传入原函数,避免位置参数冲突:
修改装饰器中调用原函数的代码:
# 原代码:return f(current_user, *args, **kwargs) return f(*args, current_user=current_user, **kwargs)
对应的视图函数需要定义关键字参数(可设为可选参数,提升装饰器通用性):
def get_banner(lang, current_user=None): # 业务逻辑代码
内容的提问来源于stack exchange,提问作者yavuzakyazici
相关产品推荐
相关产品推荐

