Return different serializer after create() in CreateAPIView in Django REST Framework

Viewed 5860

I'm using Django 2.2 and Django REST Framework.

I have to serializers for the same model.

class OrderListSerializer(serializers.ModelSerializer):
    plan = PlanBaseSerializer(read_only=True, many=False)

    class Meta:
        model = Order
        fields = [
            'id', 'name', 'plan', 'pricing',
            'created', 'completed',
        ]


class OrderCreateSerializer(serializers.ModelSerializer):
    plan_pricing = serializers.IntegerField(required=True, write_only=True)

    class Meta:
        model = Order
        fields = [
            'plan_pricing'
        ]

    def create(self, validated_data):
        plan_pricing_ = validated_data.pop('plan_pricing', None)
        try:
            plan_pricing = PlanPricing.objects.get(pk=plan_pricing_)
        except PlanPricing.DoesNotExists:
            raise ValidationError('Plan pricing not available')

        validated_data['plan'] = plan_pricing.plan
        validated_data['amount'] = plan_pricing.price

        return super().create(validated_data)

OrderListSerializer serializer is used for listing orders or order detail view and OrderCreateSerializer is used for creating a new order instance.

The view is

class CreateOrderView(generics.CreateAPIView):
    serializer_class = OrderCreateSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

This is working fine as the order object is creating as expected. But the returned value contains no data.

I want to use OrderListSerializer to render saved order details after creating the order.

How to change the serializer class after creating the object?

Also, I have to trigger a signal after the object has been successfully created. What is the best place to trigger a signal?

3 Answers

Change CreateOrderView as below,

class CreateOrderView(generics.CreateAPIView):
    serializer_class = OrderCreateSerializer

    def perform_create(self, serializer):
        return serializer.save(user=self.request.user)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        instance = self.perform_create(serializer)
        instance_serializer = OrderListSerializer(instance)
        return Response(instance_serializer.data)

serializer.save() returns the instance that just created or updated. So we use that istance to pass to the OrderListSerializer and returning the corresponding response.

You could overwrite create(), and return whatever you want:

from rest_framework import response, status
(...)
    def create(self, request, *args, **kwargs):
        super().create(request, *args, **kwargs)
        return response.Response(status=status.HTTP_201_CREATED)
(...)

There are several ways you can use here. First,

class CreateOrderView(generics.ListCreateAPIView):
    serializer_class = OrderCreateSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    def list(self, *args, **kwargs):
        serializer_class = OrderListSerializer
        serializer = serializer_class(self.get_queryset())
        return Response(serializer.data)

The alternative would be a conditional if statement, where

if self.request.method=='POST':
   self.serializer_class = OrderCreateSerializer
elif self.request.method=='GET':
   self.serializer_class = OrderListSerializer
Related