django-rest-framework multiple serializer for 1 model?
Asked Answered
K

1

6

Suppose you want to give out

{field1, field2, field3} on detail request.
{field1, field2} on list request.
{field1} on some other simpler list request.

I have seen examples using get_serializer_class with self.action which can handle detail vs list scenario. (https://mcmap.net/q/99051/-django-rest-framework-use-different-serializers-in-the-same-modelviewset)

Should I define two viewsets and two url endpoints?
Or is there a better approach here?

I guess this could be applied to tastypie as well. (two resources?)

Kilogrammeter answered 18/9, 2014 at 5:25 Comment(1)
Possible duplicate of Django Rest Framework: Dynamically return subset of fieldsCorn
P
2

I haven't tested it myself but I think you can do it overriding the methods you need.

According to the documentation (Marking extra actions for routing) you could do:

class UserViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.

If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""

def list(self, request):
    pass

def create(self, request):
    pass

def retrieve(self, request, pk=None):
    pass

def update(self, request, pk=None):
    pass

def partial_update(self, request, pk=None):
    pass

def destroy(self, request, pk=None):
    pass

Or if you need custom methods:

from django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer

class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer

@detail_route(methods=['post'])
def set_password(self, request, pk=None):
    user = self.get_object()
    serializer = PasswordSerializer(data=request.DATA)
    if serializer.is_valid():
        user.set_password(serializer.data['password'])
        user.save()
        return Response({'status': 'password set'})
    else:
        return Response(serializer.errors,
                        status=status.HTTP_400_BAD_REQUEST)

@list_route()
def recent_users(self, request):
    recent_users = User.objects.all().order('-last_login')
    page = self.paginate_queryset(recent_users)
    serializer = self.get_pagination_serializer(page)
    return Response(serializer.data)
Pyxie answered 18/9, 2014 at 7:42 Comment(1)
ok, with @list_route, you can add multiple list end points, with the code #22617473, I can achieve the desired effect.Kilogrammeter

© 2022 - 2024 — McMap. All rights reserved.