将请求上下文从 Django Rest Framework 中的 Viewset 传递到序列化程序
Pass request context to serializer from Viewset in Django Rest Framework
我有一个案例,其中序列化程序字段的值取决于当前登录用户的身份。我已经看到如何在初始化序列化程序时将用户添加到上下文中,但我不确定在使用 ViewSet 时如何执行此操作,因为您只提供序列化程序 class 而不是实际的序列化程序实例。
基本上我想知道如何去:
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
抱歉,如果不清楚,来自文档:
Adding Extra Context
哪个说要做
serializer = AccountSerializer(account, context={'request': request})
serializer.data
但我不确定如何从视图集中自动执行此操作,因为我只能更改序列化程序 class,而不能更改序列化程序实例本身。
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
Return 覆盖函数 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
这非常稳定,因为每次我们请求视图集时,它也会 returns 上下文。
the values for a serializer field depend on the identity of the currently logged in user
这就是我在 ModelViewSet 中处理此类情况的方式:
def perform_create(self, serializer):
user = self.request.user
if user.username == 'myuser':
serializer.data['myfield'] = 'something'
serializer.save()
只需在您的视图集中使用 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)
对于基于函数的视图,您可以按如下方式传递请求或用户:
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)
如果有更好的方法,请随时告知。
只需在您的 class 中添加这 2 行方法即可。
def get_serializer_context(self):
return {'request': self.request}
由于发布的答案有部分正确性,为了完整性起见在此进行总结。
- 覆盖 get_serializer_context..AND
- 在您的视图中使用 get_serializer 而不是手动调用序列化程序
我有一个案例,其中序列化程序字段的值取决于当前登录用户的身份。我已经看到如何在初始化序列化程序时将用户添加到上下文中,但我不确定在使用 ViewSet 时如何执行此操作,因为您只提供序列化程序 class 而不是实际的序列化程序实例。
基本上我想知道如何去:
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
抱歉,如果不清楚,来自文档: Adding Extra Context 哪个说要做
serializer = AccountSerializer(account, context={'request': request})
serializer.data
但我不确定如何从视图集中自动执行此操作,因为我只能更改序列化程序 class,而不能更改序列化程序实例本身。
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
Return 覆盖函数 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
这非常稳定,因为每次我们请求视图集时,它也会 returns 上下文。
the values for a serializer field depend on the identity of the currently logged in user
这就是我在 ModelViewSet 中处理此类情况的方式:
def perform_create(self, serializer):
user = self.request.user
if user.username == 'myuser':
serializer.data['myfield'] = 'something'
serializer.save()
只需在您的视图集中使用 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)
对于基于函数的视图,您可以按如下方式传递请求或用户:
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)
如果有更好的方法,请随时告知。
只需在您的 class 中添加这 2 行方法即可。
def get_serializer_context(self):
return {'request': self.request}
由于发布的答案有部分正确性,为了完整性起见在此进行总结。
- 覆盖 get_serializer_context..AND
- 在您的视图中使用 get_serializer 而不是手动调用序列化程序