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

58wvjzkj  于 2023-02-14  发布在  Go
关注(0)|答案(7)|浏览(167)

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

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

但我不确定如何从视图集中自动完成这一操作,因为我只能更改序列化程序类,而不能更改序列化程序示例本身。

e0bqpujr

e0bqpujr1#

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().get_serializer_context()
        context.update({"request": self.request})
        return context

对于Python 2.7,请使用context = super(MyModelViewSet, self).get_serializer_context()

cngwdvgl

cngwdvgl2#

对于基于函数的视图,可按如下方式传递requestuser

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

您的Serializer可能如下所示:

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

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

如果有更好的方法来做到这一点,请随时通知。

v440hwme

v440hwme3#

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

lsmd5eda4#

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

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

py49o6xq

py49o6xq5#

序列化程序字段的值取决于当前登录用户的身份
下面是我在ModelViewSet中处理此类情况的方法:

def perform_create(self, serializer):

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

    serializer.save()
7uzetpgm

7uzetpgm6#

只需在类中添加这个2行的方法,就可以开始了。

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

nue99wik7#

因为张贴的答案部分正确,为了完整起见,在此总结。
1.重写get序列化程序上下文..AND
1.在视图中使用get_serializer,而不是手动调用序列化程序

相关问题