将请求上下文从 Django Rest Framework 中的 Viewset 传递给序列化程序
Posted
技术标签:
【中文标题】将请求上下文从 Django Rest Framework 中的 Viewset 传递给序列化程序【英文标题】:Pass request context to serializer from Viewset in Django Rest Framework 【发布时间】: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
,但它不起作用!
【参考方案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)
如果有更好的方法,请随时告知。
【讨论】:
以上是关于将请求上下文从 Django Rest Framework 中的 Viewset 传递给序列化程序的主要内容,如果未能解决你的问题,请参考以下文章
Django Rest Frame API:ModelSerializer 中的附加字段
如何解决 django rest-framework 中的错误请求
我需要显示与相同模型有多对多关系的相关字段。 Django Rest Frame工作
Django REST Framework:序列化程序上下文如何工作?
如何使用 Axios 将 CSRF Cookie 从 React 发送到 Django Rest Framework