将请求上下文从Django Rest Framework中的Viewset传递给序列化程序

时间:2015-06-24 23:19:17

标签: django django-rest-framework serializer

我有一种情况,其中序列化器字段的值取决于当前登录用户的身份。我已经看到了在初始化序列化程序时如何将用户添加到上下文中,但是我不确定在使用ViewSet时如何执行此操作,因为您只提供序列化程序类而不是实际的序列化程序实例。

基本上我想知道如何去:

class myModelViewSet(ModelViewSet):
   queryset = myModel.objects.all()
   permission_classes = [DjangoModelPermissions]
   serializer_class = myModelSerializer

为:

class myModelSerializer(serializers.ModelSerializer):
    uploaded_by = serializers.SerializerMethodField()
    special_field = serializers.SerializerMethodField()

    class Meta:
        model = myModel

    def get_special_field(self, obj):
        if self.context['request'].user.has_perm('something.add_something'):
           return something

对不起,如果不清楚,来自DOC: Adding Extra Context 哪个说要做

serializer = AccountSerializer(account, context={'request': request})
serializer.data

但我不确定如何从视图集中自动执行此操作,因为我只能更改序列化程序类,而不是序列化程序实例本身。

5 个答案:

答案 0 :(得分:67)

GenericViewSet包含您可以覆盖的get_serializer_context方法:

class myModelViewSet(ModelViewSet):
    queryset = myModel.objects.all()
    permission_classes = [DjangoModelPermissions]
    serializer_class = myModelSerializer

    def get_serializer_context(self):
        return {'request': self.request}

答案 1 :(得分:1)

在覆盖函数get_serializer_context中返回父上下文将使访问请求及其数据变得容易。

 class myModelViewSet(ModelViewSet):
       queryset = myModel.objects.all()
       permission_classes = [DjangoModelPermissions]
       serializer_class = myModelSerializer

       def get_serializer_context(self):
       """
       pass request attribute to serializer
       """
           context = super(myModelViewSet, self).get_serializer_context()
           return context

这非常稳定,因为每次我们请求viewset时,它都会返回上下文。

答案 2 :(得分:1)

在视图集中使用get_serializer()

def get_serializer(self, *args, **kwargs):
    """
    Return the serializer instance that should be used for validating and
    deserializing input, and for serializing output.
    """
    serializer_class = self.get_serializer_class()
    kwargs['context'] = self.get_serializer_context()
    return serializer_class(*args, **kwargs)

答案 3 :(得分:0)

  

序列化程序字段的值取决于当前登录用户的标识

这就是我在ModelViewSet中处理这种情况的方法:

def perform_create(self, serializer):

    user = self.request.user
    if user.username == 'myuser':
        serializer.data['myfield'] = 'something'

    serializer.save()

答案 4 :(得分:0)

对于基于功能的视图,您可以按照以下方式传递请求或用户:

serializer = ProductSerializer(context = {'request':request},data=request.data)

您的序列化器可能如下所示:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model    = Product
        fields   = ['id']

    def create(self, validated_data):
        user =  self.context['request'].user
        print("User is")
        print(user)

请随时告知是否还有更好的方法。