Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically include or exclude Serializer class fields

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:

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 a lot cleaner if the field email would be completely excluded from the serializer output it show_email is False, instead showing that ugly "email": null thing.

How could I do that?

like image 686
César García Tapia Avatar asked Sep 15 '13 13:09

César García Tapia


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

Which class allows you to automatically create a serializer?

The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.

What does serializer Is_valid do?

is_valid perform validation of input data and confirm that this data contain all required fields and all fields have correct types. If validation process succeded is_valid set validated_data dictionary which is used for creation or updating data in DB.


1 Answers

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.

like image 82
Fiver Avatar answered Nov 04 '22 11:11

Fiver