Part 2: Building the Orders API

I finished section 10 - Updating an Order of Building the Orders API, and my OrderViewSet looks like this:

class OrderViewSet(ModelViewSet):
    http_method_names = ['get', 'patch', 'delete', 'head', 'options']
    
    def get_permissions(self):
        if self.request.method in ['PATCH', 'DELETE']:
            return [IsAdminUser()]
        return [IsAuthenticated()]

    def create(self, request, *args, **kwargs):
        serializer = CreateOrderSerializer(
                        data=request.data,
                        context={'user_id': self.request.user.id})
        serializer.is_valid(raise_exception=True)
        order = serializer.save()
        serializer = OrderSerializer(order)
        return Response(serializer.data)

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return CreateOrderSerializer
        elif self.request.method == 'PATCH':
            return UpdateOrderSerializer
        return OrderSerializer
    
    def get_queryset(self):
        user = self.request.user
        if user.is_staff:
            return Order.objects.all()
        
        customer_id = Customer.objects.only('id').get(user_id=user.id)
        return Order.objects.filter(customer_id=customer_id)

So I’m seeing a problem here: we can’t POST orders anymore (can’t create a new order!).

Even though a POST request would get routed through the get_serializer_class() method, it’s no longer one of the allowed http_method_names and so this removes it from our endpoint; nor is it in the get_permissions() method. So, effectively, our application can’t create new orders since we can’t make a POST request at http://127.0.0.1:8000/store/orders/

Why remove this functionality?

I wanted the ability to create a cart back in the application, so I added ‘post’ to the http_method_names, and added ‘POST’ to the get_permissions() method. The top of my OrderViewSet now looks like this:

class OrderViewSet(ModelViewSet):
    http_method_names = ['get', 'post', 'patch', 
                        'delete', 'head', 'options']
    
    def get_permissions(self):
        if self.request.method in ['POST','PATCH', 'DELETE']:
            return [IsAdminUser()]
        return [IsAuthenticated()]
...

Did anyone else run across this? What are your thoughts?

Thanks!

Ah, at time 4:50 of Lesson 12 – Creating Custom Signals, Mosh adds “post” into the http_method_names.

But now I also understand why it doesn’t need to be in the get_permissions() method: the POST functionality needs to be there for non-Admin users. Duh.

So the beginning of the OrderViewSet should be:

class OrderViewSet(ModelViewSet):
    http_method_names = ['get', 'post', 'patch', 
                        'delete', 'head', 'options']
    
    def get_permissions(self):
        if self.request.method in ['PATCH', 'DELETE']:
            return [IsAdminUser()]
        return [IsAuthenticated()]
    
    ...