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
相关产品推荐
相关产品推荐

