嵌套序列化程序中的上下文django休息框架 [英] context in nested serializers django rest framework
问题描述
如果我有一个嵌套的序列化程序:
class ChildSerializer(ModelSerializer):
pre>
class Meta:
fields =('c_name',)
model = Child
class ParentSerializer(ModelSerializer):
child = ChildSerializer(many = read_only = True
class Meta:
model = Parent
fields =('p_name','child')
我想访问嵌套的序列化程序中的上下文,我该怎么做?据我所知,上下文不会传给孩子。
我希望能够为每个用户在字段上实现权限模型,因为我覆盖了ModelSerializer的get_fields()方法:
def get_fields(self):
fields = super()。get_fields()
....
for f在字段中:
如果has_rights(self.context ['request']。user,f,read):
ret_val [f] = fields [f]
....
return ret_val
哪些适用于常规序列化程序,但是上下文,因此请求和用户当嵌套的子代被传递给get_fields()时不可用。串行器嵌套时,如何访问上下文?
解决方案我找到了一个工作的解决方案。我用ParentizerMethodField替代了Parent类中的ChildSerializer赋值,该方法添加了上下文。然后将其传递给CustomModelSerializer中的get_fields方法:
class ChildSerializer(CustomModelSerializer):
class Meta:
fields =('c_name',)
model = Child
class ParentSerializer(CustomModelSerializer):
child = serializers.SerializerMethodField 'get_child_serializer'
class Meta:
model = Parent
fields =('p_name','child')
def get_child_serializer(self, obj)
serializer_context = {'request':self.context.get('request')}
children = Child.objects.all()。filter(parent = obj)
serializer = ChildSerializer(children,many = True,context = serializer_context)
return serializer.data
在我的CustomModelSerializer中:
class CustomModelSerializer(rest_serializer_classes.HyperlinkedModelSerializer):
def __init __(self,* args,** kwargs):
确保用户耦合到序列化程序(需要权限)
super ().__ init __(* args,** kwargs)
如果不是self.context:
self._context = getattr(self.Meta,'context',{})
try:
self.user = self.context ['request']。user
除了KeyError:
self.user = None
def get_fields(self) :
ret = OrderedDict()
如果不是self.user:
print(没有用户与对象关联)
return ret
fields = super()。get_fields()
#超级用户
如果self.user.is_superuser:
返回字段的Bypass权限
f在字段中:
if has_right(self.user,self.Meta.model .__ name __。lower(),f,read):
ret [f] = fields [f]
return ret
这似乎工作正常,孩子的字段在序列化程序中被丢弃我可以撤销 Child.c_name 或 Parent.child
If i have a nested serializer:
class ChildSerializer(ModelSerializer): class Meta: fields = ('c_name', ) model = Child class ParentSerializer(ModelSerializer): child = ChildSerializer(many=True, read_only=True) class Meta: model = Parent fields = ('p_name', 'child')
And i want to access the context in the nested serializer, how can i do that? As far as i can tell, context isn't passed to the Child.
I want to be able to implement a permission model per user on fields, for that i overridden the get_fields() method of the ModelSerializer:
def get_fields(self): fields = super().get_fields() .... for f in fields: if has_rights(self.context['request'].user, f, "read"): ret_val[f] = fields[f] .... return ret_val
Which works for regular serializers, but the context, and thus the request and user are not available when the nested child is passed to get_fields(). How do i access the context when the serializer is nested?
解决方案Ok i found a working solution. I replaced the ChildSerializer assignment in the Parent class with a SerializerMethodField which adds the context. This is then passed to the get_fields method in my CustomModelSerializer:
class ChildSerializer(CustomModelSerializer): class Meta: fields = ('c_name', ) model = Child class ParentSerializer(CustomModelSerializer): child = serializers.SerializerMethodField('get_child_serializer') class Meta: model = Parent fields = ('p_name', 'child') def get_child_serializer(self, obj): serializer_context = {'request': self.context.get('request') } children = Child.objects.all().filter(parent=obj) serializer = ChildSerializer(children, many=True, context=serializer_context) return serializer.data
and in my CustomModelSerializer:
class CustomModelSerializer(rest_serializer_classes.HyperlinkedModelSerializer): def __init__(self, *args, **kwargs): """ Make sure a user is coupled to the serializer (needed for permissions) """ super().__init__(*args, **kwargs) if not self.context: self._context = getattr(self.Meta, 'context', {}) try: self.user = self.context['request'].user except KeyError: self.user = None def get_fields(self): ret = OrderedDict() if not self.user: print("No user associated with object") return ret fields = super().get_fields() # Bypass permission if superuser if self.user.is_superuser: return fields for f in fields: if has_right(self.user, self.Meta.model.__name__.lower(), f, "read"): ret[f] = fields[f] return ret
This seems to work fine, and fields of the child are discarded in the serializer when i either revoke read-rights on Child.c_name or on Parent.child
这篇关于嵌套序列化程序中的上下文django休息框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!