There are instances where a generic view wont quite work for us. Look at our ProductDetail view like this, it provides methods for GET, PUT and DELETE. But the thing is, there is a generic view that provides all those operations.
'''this is our current ProductDetail view'''class ProductDetail(APIView): def get(self, request, id): product = get_object_or_404(Product, pk=id) serializer = ProductSerializer(product) return Response(serializer.data)
def put(self, request, id): product = get_object_or_404(Product, pk=id) serializer = ProductSerializer(product, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data)
def delete(self, request, id): product = get_object_or_404(Product, pk=id) if product.orderitems_set.count() > 0: return Response({'error': 'Product cannot be deleted because it is associated with an order item'}, status=HTTP_405) product.delete() return Response(status=status.HTTP_204_NO_CONTENT)This generic view is the RetrieveUpdateDestroyAPIView. Now you need to make you ProductDetail class inherit from this generic view, and then provide it with two attributes. The first one is the queryset, and the second one is the serializer_class. see below
from rest_framework.generics import RetrieveUpdateDestroyAPIView
class ProductDetail(RetrieveUpdateDestroyAPIView): queryset = Product.objects.all() serializer_class = ProductSerializer
def delete(self, request, pk): product = get_object_or_404(Product, pk=pk) if product.orderitems_set.count() > 0: return Response({'error': 'Product cannot be deleted because it is associated with an order item'}, status=HTTP_405) product.delete() return Response(status=status.HTTP_204_NO_CONTENT)
''' note how we are using pk instead of id, if we use pk, we have to make sure that our url pattern also accepts pk as the lookup type..but lets say we strictly want to use id, we can do that by setting lookup_field = "id" '''After doing this, you can remove the GET and PUT methods in the class since all that logic has been done in the generic view we are inheriting from.
But lets look at the DELETE method, here we have some logic that is specific to our application. None of the mixins in DRF know about the product, orderitems etc. So here, we need to override the DELETE method that we have inherited from the RetrieveUpdateDestroyAPIView class. That is why we didnt delete the delete method in our ProductDetail class