Dynamically include or exclude Serializer class fields

后端 未结 3 643
名媛妹妹
名媛妹妹 2021-02-09 05:56

In my User profile model I\'ve included a show_email field explicitly. So, to add this feature to my API, the UserSerializer class looks like this:

相关标签:
3条回答
  • 2021-02-09 06:26

    You could override restore_fields method on serializer. Here in restore_fields method you can modify list of fields - serializer.fields - pop, push or modify any of the fields.

    eg: Field workspace is read_only when action is not 'create'

    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')
    
    0 讨论(0)
  • 2021-02-09 06:39

    This answer comes late but for future google searches: there is an example in the documentation about Dynamically modifying fields. So, by passing an argument to the serializer, you control whether or not a field is processed:

    serializer = MyPostSerializer(posts, show_email=permissions)
    

    and then in the init function in the serializer you can do something like:

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

    Now the show_email field will be ignored by the serializer.

    0 讨论(0)
  • 2021-02-09 06:43

    You could do this in your API view by overriding the method returning the response, i.e. the "verb" of the API view. For example, in a ListAPIView you would override 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
    

    You would probably want to add some more checking for attributes, but that's the gist of how it could be done. Also, I would add that removing fields from some results may cause issues for the consuming application if it expects them to be present for all records.

    0 讨论(0)
提交回复
热议问题