1

I have a Django REST Framework serializer that is used in several places. One of the fields is a SerializerMethodField that I only wanted to include if the serializer is used to serialize only a single object. Basically, I want to not include one of the SerializerMethodField (or change it's behavior) when I have that MySerializer(objects, many=True). Any ideas how to do this?

AKX
  • 152,115
  • 15
  • 115
  • 172
Iga Quintana
  • 129
  • 3
  • 7
  • Does this answer your question? [Django rest framework, use different serializers in the same ModelViewSet](https://stackoverflow.com/questions/22616973/django-rest-framework-use-different-serializers-in-the-same-modelviewset) – Dušan Maďar Sep 07 '20 at 06:37
  • @DušanMaďar That can work but requires to write a separate serializer. Just wondering if there's a solution to use the same one. – Iga Quintana Sep 07 '20 at 06:41
  • 1
    You could just subclass from `MySerializer` to be e.g. `MyListSerializer`; you can also subclass `MySerializer.Meta` within your new `MyListSerializer` and e.g. remove entries from `fields`. – AKX Sep 07 '20 at 06:49

2 Answers2

2

Hi here is my solution to determine if we are in context of many=True: I override the new class method and add a "has_many" key to the context kwargs object:

    class MySerializer(serializer.ModelSerializer):

        def __new__(cls, *args, **kwargs):
            if kwargs.get('many', False) is True:
                context = kwargs.get('context', {})
                context.update({'has_many': True})
                kwargs.update({'context': context})

            return super().__new__(cls, *args, **kwargs)

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            if self.context.get('has_many', False):
                # Do something
Dharman
  • 30,962
  • 25
  • 85
  • 135
eInyzant
  • 269
  • 2
  • 5
1

One easy way to dynamically remove fields from your serializer is to add following codes to your serializer:

class MySerializer(serializer.ModelSerializer):
    def __init__(self, *args, **kwargs):
        remove_fields = kwargs.pop('remove_fields', None)
        super(MySerializer, self).__init__(*args, **kwargs)

        if remove_fields:
            # for multiple fields in a list
            for field_name in remove_fields:
                self.fields.pop(field_name, None)

And then when you need to remove some fields from your serializer is to use MySerializer(objects, many=True, remove_fields=['list_of_your_fields',]) which will remove list_of_your_fields' fields from your output data

Roham
  • 1,970
  • 2
  • 6
  • 16