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

ViewSet中@action装饰的接口无法获取request数据,触发AttributeError

问题:DRF ViewSet @action 接口中 Serializer 无法获取 Request 对象

我在Django REST Framework中定义了一个ViewSet,并用@action装饰器添加了额外接口/api/users/subscriptions。Serializer内通过SerializerMethodField定义了一个依赖request.user的字段:

# Serializer示例代码
class UserSerializer(serializers.ModelSerializer):
    extra_field = serializers.SerializerMethodField()

    def get_extra_field(self, obj):
        user = self.context.get('request').user
        # 基于当前用户处理逻辑
        return ...

    class Meta:
        model = User
        fields = ['id', 'username', 'extra_field']

调用ViewSet默认接口(如/api/users/)时一切正常,但调用/api/users/subscriptions接口时,Serializer的self.context为空,执行self.context.get('request').user时触发错误:

AttributeError: 'NoneType' object has no attribute 'user'

解决方案

1. 在@action方法中手动传递context到Serializer

在自定义的@action视图方法里,实例化Serializer时手动传入包含request的context:

from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()

    @action(detail=False, methods=['get'])
    def subscriptions(self, request):
        # 示例:获取当前用户的订阅数据
        queryset = self.queryset.filter(subscribed_users=request.user)
        # 手动传入context
        serializer = self.serializer_class(queryset, many=True, context={'request': request})
        return Response(serializer.data)

2. 重写ViewSet的get_serializer_context方法(推荐)

如果ViewSet中有多个自定义@action方法,重写get_serializer_context可以统一确保所有Serializer实例都能获取到request:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()

    def get_serializer_context(self):
        # 继承父类的context,再确保request存在
        context = super().get_serializer_context()
        context['request'] = self.request
        return context

    @action(detail=False, methods=['get'])
    def subscriptions(self, request):
        queryset = self.queryset.filter(subscribed_users=request.user)
        # 无需手动传context,get_serializer会自动使用重写后的context
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

问题根源

DRF的默认ViewSet动作(list、retrieve等)会自动将request、view等核心对象注入到Serializer的context中,但自定义@action方法如果没有通过get_serializer或者手动传递context,就会导致context缺失request对象,进而引发报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:54:56