嵌套序列化程序中的上下文 Django 休息框架

新手上路,请多包涵

如果我有一个嵌套的序列化程序:

 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')

我想访问嵌套序列化程序中的上下文,我该怎么做?据我所知,上下文没有传递给孩子。

我希望能够在字段上为每个用户实现一个权限模型,为此我重写了 ModelSerializer 的 get_fields() 方法:

 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

这适用于常规序列化器,但是当嵌套子级传递给 get_fields() 时,上下文以及请求和用户不可用。嵌套序列化程序时如何访问上下文?

原文由 Robin van Leeuwen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 702
2 个回答

好的,我找到了一个可行的解决方案。我用添加上下文的 SerializerMethodField 替换了 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):
        """
            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

这似乎工作正常,当我撤销对 _Child.cnameParent.child 的读取权限时,子项的字段在序列化程序中被丢弃

原文由 Robin van Leeuwen 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果你不能改变你的子序列化器的性质,就像@Kirill Cherepanov 和@Robin van Leeuwen 的回答一样,一个简单 但不完全集成的 解决方案是手动传递 __init__() 函数中的上下文:

 class ChildSerializer(CustomModelSerializer):
    class Meta:
        fields = ('c_name', )
        model = Child

class ParentSerializer(CustomModelSerializer):

    child = ChildSerializer(many=True, read_only=True)

    class Meta:
        model = Parent
        fields = ('p_name', 'child')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # We pass the "upper serializer" context to the "nested one"
        self.fields['child'].context.update(self.context)

原文由 Timothé Delion 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题