blue_zinc
blue_zinc

Reputation: 2500

Django Rest Framework: Change Serializer or Add Field Based on Authentication

I have a viewset as follows:

class CardViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Standard Viewset for listing cards
    """
    pagination_class = StandardCellSetPagination
    permission_classes = [AllowAny, IsAuthenticated]

    def list(self, request):
        queryset = Card.objects.exclude(reply_to__isnull=False).order_by('-created')
        cards = self.paginate_queryset(queryset)
        serializer = CardCellSerializer(cards, many=True)
        return self.get_paginated_response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = Card.objects.all()
        card = get_object_or_404(queryset, pk=pk)
        serializer = CardSerializer(card)
        return Response(serializer.data)

My serializer for the CardSerializer is:

class CardSerializer(serializers.ModelSerializer):
    class Meta:
        model = Card

How do I either

Such that I can return True / False if a user has favorited the card via a SerializerMethodField

Upvotes: 4

Views: 3492

Answers (1)

Ivan
Ivan

Reputation: 6013

You can do this:

def retrieve(self, request, pk=None):
    queryset = Card.objects.all()
    card = get_object_or_404(queryset, pk=pk)

    # Same for list method
    if request.user and request.user.is_authenticated:
        serializer = AuthenticatedCardSerializer(card)
    else:
        serializer = CardSerializer(card)

    return Response(serializer.data)

AuthenticatedCardSerializer could then extend CardSerializer to include any fields visible to authenticated users.

Also if you decide to use same serialization behavior for list and retrieve, you could override get_serializer_class in your viewset instead:

def get_serializer_class(self):
    if self.request.user and self.request.user.is_authenticated:
        return AuthenticatedCardSerializer
    else:
        return CardSerializer

and leave everything else to the default list/retrieve implementations.

As an alternative, you could add the field in serializer's __init__. You can get the request from the context kwarg, do the same check and add any fields you need. I think though that it is needlessly more complicated than just having two serializers.

Upvotes: 9

Related Questions