【问题标题】:Pass request context to serializer from Viewset in Django Rest Framework将请求上下文从 Django Rest Framework 中的 Viewset 传递给序列化程序
【发布时间】:2015-09-11 08:59:52
【问题描述】:

我有一种情况,序列化器字段的值取决于当前登录用户的身份。我已经看到了如何在初始化序列化程序时将用户添加到上下文中,但我不确定在使用 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

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

【问题讨论】:

  • 你试过self.context.get('request').user.has_perm("some.permission")吗?
  • 您希望something 在输出中与序列化程序的其他字段一起返回吗?
  • 对不起,如果不清楚,问题是 self.context 在序列化程序中是空的。
  • AccountSerializer(account, context={'request': request}) 是我所需要的一切
  • citynorman 你在哪里定义请求?我尝试将请求定义为:context={'request': { 'user': self.admins[0].user }},但它不起作用!

标签: django django-rest-framework serialization


【解决方案1】:

GenericViewSet 具有 get_serializer_context 方法,可以让您更新 context

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

    def get_serializer_context(self):
        context = super(myModelViewSet, self).get_serializer_context()
        context.update({"request": self.request})
        return context

【讨论】:

  • 选择这个作为最佳答案。我相信这会解决我的问题(如果这实际上是我的问题)。结果我错过了在这种情况下我手动实例化序列化程序的事实,并且它没有被视图集路由。哦。
  • 对我来说:NameError: name 'request' is not defined
  • @Coderaemon 你解决了吗?这就是我得到的:/上下文没有传递给序列化程序
  • 最新的 DRF 在发送到序列化程序的默认上下文中包含self.request;你不需要手动添加它。
  • 对于每个收到请求的人 KeyError:您可以通过使用请求对象从视图初始化序列化程序来解决此问题,如下所示:serializer = serializers.RandomSerializer(data=request.data, context={ 'request':request}) 来源:django-rest-framework.org/api-guide/serializers/…
【解决方案2】:

在覆盖函数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

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

【讨论】:

    【解决方案3】:

    序列化器字段的值取决于当前登录用户的身份

    这就是我在 ModelViewSet 中处理此类情况的方式:

    def perform_create(self, serializer):
    
        user = self.request.user
        if user.username == 'myuser':
            serializer.data['myfield'] = 'something'
    
        serializer.save()
    

    【讨论】:

      【解决方案4】:

      只需在视图集中使用 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)
      

      【讨论】:

      • 你的 ViewSet 应该是 GenericViewSet 的子类
      【解决方案5】:

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

      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)
      

      如果有更好的方法,请随时告知。

      【讨论】:

        猜你喜欢
        • 2016-09-25
        • 2020-09-14
        • 2018-06-13
        • 2017-07-21
        • 1970-01-01
        • 1970-01-01
        • 2016-05-12
        • 2014-05-24
        • 2015-09-27
        相关资源
        最近更新 更多