You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django ListView使用method_decorator报缺少request参数错误

问题现象

Django项目开发中,给类视图方法添加自定义权限装饰器后,运行触发报错:
_wrapped_view() missing 1 required positional argument: 'request'
该装饰器在普通函数视图场景下使用无异常,触发报错的原代码如下:

class AudienceListView(ListView):
    model = Audience
    template_name = 'audience/list.html'

    @method_decorator(company_user_has_permission('audiences_view'))
    def get_queryset(self):
        queryset = super().get_queryset()
        company = Company.get_current(self.request)
        return queryset.filter(company=company) \
            .annotate(total_deals=Count("deals"), total_contacts=Count("contacts")) \
            .order_by('-id')
报错根因

用于权限校验的视图装饰器,默认会从被装饰方法的第一个位置参数获取request请求对象。
把装饰器直接加在get_queryset方法上存在两个问题:

  • 类实例方法的第一个位置参数永远是类实例本身self,不是request
  • get_queryset是类视图内部被调度调用的辅助方法,不是直接接收请求的入口方法
    装饰器运行时把self错当成request读取,自然会提示缺少必填的request位置参数。
修复方案

权限类装饰器需要加在类视图的请求入口方法上,不要加在内部辅助方法上,两种标准写法任选其一即可:

  • 写法1:类层面装饰,指定作用于dispatch入口方法
from django.utils.decorators import method_decorator

@method_decorator(company_user_has_permission('audiences_view'), name='dispatch')
class AudienceListView(ListView):
    model = Audience
    template_name = 'audience/list.html'

    def get_queryset(self):
        queryset = super().get_queryset()
        company = Company.get_current(self.request)
        return queryset.filter(company=company) \
            .annotate(total_deals=Count("deals"), total_contacts=Count("contacts")) \
            .order_by('-id')
  • 写法2:重写dispatch方法,在方法上加装饰器
from django.utils.decorators import method_decorator

class AudienceListView(ListView):
    model = Audience
    template_name = 'audience/list.html'

    @method_decorator(company_user_has_permission('audiences_view'))
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        queryset = super().get_queryset()
        company = Company.get_current(self.request)
        return queryset.filter(company=company) \
            .annotate(total_deals=Count("deals"), total_contacts=Count("contacts")) \
            .order_by('-id')

调整后装饰器可以正确从入口方法的第一个位置参数拿到request对象完成权限校验,代码可正常运行。

内容的提问来源于stack exchange,提问作者jake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:27:21