Home > Software engineering >  Display fields based on the request in django-rest-framework serializer
Display fields based on the request in django-rest-framework serializer

Time:08-19

I have a Post model in my Django project. I want to display description field when the user receives the list of posts, and when he receives a post instance, display the body field instead. (Both fields exist separately in the model)

here is my Post serializer:

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'image', 'description', 'slug']
        lookup_field = 'slug'

this is my view:

class posts(viewsets.ModelViewSet):
    queryset = Post.published.all()
    serializer_class = PostSerializer
    lookup_field = 'slug'

I want when the user gets the posts list in /posts/ url, see something like this:

[
    {
        "id": 31,
        "title": "hello-world",
        "image": { ... },
        "description": "post description",
        "slug": "hello-world"
    },
    ...
]

and when get a post instance, see something like this with additional body field and exclude the description field:

{
    "id": 31,
    "title": "hello-world",
    "image": { ... },
    "body": "post body ...",
    "slug": "hello-world"
}

CodePudding user response:

I would suggest you to use different serializers, It will be better to have a logical separation between different requirements

class PostListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'image', 'description', 'slug']
        <...other attributes here ..>
        

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'image', 'body', 'slug']
        < ...other_attributes_here.. >

you can modify your viewset to select serializer based on action

class Posts(viewsets.ModelViewSet):
    queryset = Post.published.all()
    serializer_class = PostSerializer
    lookup_field = 'slug'

    def get_serializer_class(self):
        serializer_map = {
          'retrieve': PostSerializer,
          'list': PostListSerializer
        }

        return serializer_map.get(self.action, PostSerializer)

This should work fine.

  • Related