Django装饰器报错:wrapper()收到意外关键字参数'id'
解决Django自定义装饰器处理带关键字参数视图的报错问题
这个问题我之前在做Django项目时也踩过坑!核心原因是你自定义的login_required装饰器结构不对,没办法正确处理视图接收的关键字参数(比如路由里的id),导致触发TypeError。
问题根源分析
你原来的装饰器写法直接把view_function, request, *args, **kwargs作为顶层函数的参数,还错误地加了@decorator(这个完全没必要)。当Django路由把id作为关键字参数传递给视图时,你的装饰器没有对应的逻辑去接收和传递这些关键字参数,自然就会报“意外的关键字参数”错误。
正确的装饰器写法
Django的视图装饰器需要是嵌套函数结构:外层函数接收被装饰的视图,内层包装函数处理请求验证,并完整传递所有参数给原视图。
基础修复版本
from django.shortcuts import redirect from django.conf import settings def login_required(view_function): def wrapper(request, *args, **kwargs): # 打印参数,方便调试(可选) print(f"位置参数: {args}") print(f"关键字参数: {kwargs}") if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path)) # 把所有参数原封不动传给原视图 return view_function(request, *args, **kwargs) return wrapper
优化版本(保留原视图元信息)
建议加上functools.wraps,它会保留原视图函数的名称、文档字符串等元信息,避免Django反向解析或其他依赖函数元信息的功能出问题:
from django.shortcuts import redirect from django.conf import settings from functools import wraps def login_required(view_function): @wraps(view_function) def wrapper(request, *args, **kwargs): if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path)) return view_function(request, *args, **kwargs) return wrapper
为什么这样能解决问题?
- 内层的
wrapper函数用*args捕获所有位置参数,**kwargs捕获所有关键字参数(比如路由里的id) - 验证通过后,把这些参数完整传递给原视图函数,确保视图能拿到需要的
id参数 @wraps(view_function)让装饰后的视图保留原有的标识,避免潜在的兼容性问题
修改完装饰器后,你的detail(或者路由里的new)视图就能正常接收id参数,不会再触发类型错误了。
内容的提问来源于stack exchange,提问作者Андрей Чупрына
相关产品推荐
相关产品推荐

