动态包含或排除Serializer类字段

时间:2013-09-15 13:07:06

标签: django django-rest-framework

在我的User个人资料模型中,我明确地包含了show_email字段。因此,要将此功能添加到我的API,UserSerializer类如下所示:

class UserSerializer(serializers.ModelSerializer):
    email = serializers.SerializerMethodField('show_email')

    def show_email(self, user):
        return user.email if user.show_email else None

    class Meta:
        model = django.contrib.auth.get_user_model()
        fields = ("username", "first_name", "last_name", "email")

但我真的不喜欢它。我认为,如果字段email完全从序列化程序输出中排除show_email False,而不是显示丑陋的"email": null,那将会更加清晰。

我怎么能这样做?

3 个答案:

答案 0 :(得分:3)

您可以通过覆盖返回响应的方法(即API视图的“动词”)在API视图中执行此操作。例如,在ListAPIView中,您将覆盖get()

class UserList(generics.ListAPIView):
    model = django.contrib.auth.get_user_model()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        response = super(UserList, self).get(request, *args, **kwargs)
        for result in response.data['results']:
            if result['email'] is None:
                result.pop('email')
        return response

您可能希望添加一些属性检查,但这是如何完成它的要点。另外,我想补充一点,如果消费应用程序希望它们出现在所有记录中,那么从某些结果中删除字段可能会导致消费应用程序出现问题。

答案 1 :(得分:1)

这个答案来得晚,但对于未来的谷歌搜索:有关Dynamically modifying fields的文档中有一个例子。 因此,通过将参数传递给序列化程序,您可以控制是否处理字段:

serializer = MyPostSerializer(posts, show_email=permissions)

然后在序列化程序中的 init 函数中,您可以执行以下操作:

class MyPostSerializer(serializers.ModelSerializer):

def __init__(self, *args, **kwargs):
    show_email = kwargs.pop('show_email', None)

    # Instantiate the superclass normally
    super(DeviceSerializer, self).__init__(*args, **kwargs)

    if not show_email:
        self.fields.pop("show_email")

现在, show_email 字段将被序列化程序忽略。

答案 2 :(得分:0)

您可以覆盖序列化程序上的restore_fields方法。在restore_fields方法中,您可以修改字段列表 - serializer.fields - 弹出,推送或修改任何字段。

例如:当行动不是“创建”时,字段工作区是read_only

class MyPostSerializer(ModelSerializer):

def restore_fields(self, data, files):
    if (self.context.get('view').action != 'create'):
        self.fields.get('workspace').read_only=True
    return super(MyPostSerializer, self).restore_fields(data, files)

class Meta:
    model = MyPost
    fields = ('id', 'name', 'workspace')