1

Inside Views.py, I have these code:

class ServerViewSet(viewsets.ViewSet):

def list(self, request):
    servers = Server.objects.all()
    serializer = ServerSerializer(servers, many=True) 
    return Response(serializer.data) # In here, I want to get the server name only

def retrieve(self, request, pk=None):
    servers = get_object_or_404(Server, pk=pk)
    serializer = ServerSerializer(servers)
    return Response(serializer.data) # In here, I want to get the server name and ip address

Inside serializers.py, I have these code:

class ServerSerializer(serializers.HyperlinkedModelSerializer):
   class Meta:
        model = Server
        # fields = '__all__'
        fields = ('id', 'name', 'desc', 'ip_address')

Is there an official method to filter out the specific field from serializers.data

Sample with parent class

class CommonSerializer(serializers.ModelSerializer):
def get_field_names(self, *args, **kwargs):
    field_names = self.context.get('fields', None)
    if field_names:
        return field_names
    return super(self).get_field_names(*args, **kwargs)

class ServerSerializer(CommonSerializer):
      class Meta:
        ..............

class WebsiteSerializer(CommonSerializer):
   class Meta:
        ..............
Gary Ng
  • 413
  • 8
  • 16

1 Answers1

7

Override get_field_names in you serializer:

class ServerSerializer(serializers.HyperlinkedModelSerializer):
    def get_field_names(self, *args, **kwargs):
        field_names = self.context.get('fields', None)
        if field_names:
            return field_names

        return super(ServerSerializer, self).get_field_names(*args, **kwargs)

then use it like:

serializer = ServerSerializer(servers, context={'fields': ['name']})

serializer = ServerSerializer(servers, context={'fields': ['name', 'ip_address']})

* EDIT *

Turn it into mixin, to make it more reusable:

class FieldMixin(object):
    def get_field_names(self, *args, **kwargs):
        field_names = self.context.get('fields', None)
        if field_names:
            return field_names

        return super(FieldMixin, self).get_field_names(*args, **kwargs)

and use it:

class ServerSerializer(FieldMixin, serializers.HyperlinkedModelSerializer):
mariodev
  • 13,928
  • 3
  • 49
  • 61
  • Thanks for the answer, but when I don't pass context as parameter, the error prompt "super() argument 1 must be type, not ServerSerializer", how can I display all fields if context didn't passed – Gary Ng Nov 06 '17 at 03:21
  • @GaryNg Maybe try `_context` instead of `context`. This attribute should always exist. – mariodev Nov 06 '17 at 06:02
  • I mean that if I type "serializer = serializer = ServerSerializer(servers)", return super(self).get_field_names(*args, **kwargs) will throw exception as comment above. – Gary Ng Nov 06 '17 at 06:34
  • Use `super(ServerSerializer, self)` instead of `super(self)`. – mariodev Nov 06 '17 at 06:41
  • Yes, it works if I add this into ServerSerializer class, what I try to do is impletement parent class for these kind of serializer, would you mind to show me how to do it? – Gary Ng Nov 06 '17 at 06:50
  • I've added sample in question – Gary Ng Nov 06 '17 at 06:53
  • I found that the FieldMixin will be crashed if the field name is Serializer, please see: https://stackoverflow.com/questions/47154010/django-rest-framework-nested-serilaizer-throw-field-name-server-is-not-valid-f/47154073#47154073, hope you will have time to take a look – Gary Ng Nov 07 '17 at 10:05
  • Thank you! Working on a [fully typed Python 3 version of the mixin](https://stackoverflow.com/q/56980077/96588). – l0b0 Jul 11 '19 at 00:10