Dynamically include or exclude fields in the Serializer class

In my User profile model, I have included the show_email field explicitly. So, to add this function to your API, the UserSerializer class looks like this:

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

But I don’t really like it. I think it would be much cleaner if the email field were completely excluded from the output of the serializer it show_email is False , instead displaying this ugly thing "email": null .

How can i do this?

+6
source share
3 answers

You can do this in your API view by overriding the method that returns the response, i.e. "verb" representation of the API. For example, in ListAPIView, you 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 probably want to add some more attribute checking, but the point is how to do this. In addition, I would add that removing fields from some results can cause problems for the consumer application if it expects them to be present for all records.

+3
source

This answer is delayed, but for future Google searches: there are dynamically changing fields in the documentation. So, by passing an argument to the serializer, you control whether the field is being 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.

+1
source

You can override the restore_fields method for the serializer. Here in the restore_fields method you can change the list of fields - serializer.fields - pop, click or change any of the fields.

for example: read_only field workspace when the action does 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
source

Source: https://habr.com/ru/post/953858/


All Articles