Search code examples
djangoapidjango-rest-frameworkcartdjango-generic-views

add to cart function not working in django rest framework using functional view


I tried to create an add-to-cart api using (non api-server-side) code into Django rest framework. But when I call api in postman it shows 403 forbidden. I haven't use any serializer in this view.

Also, I tried using APIView and serializers, it doesnt work as well. I am new to django rest framework. I need help writing this.

My models:

class OrderItem(models.Model) :
    user = models.ForeignKey(User,on_delete=models.CASCADE,null=True, blank=True)
    ordered = models.BooleanField(default=False)
    item = models.ForeignKey(Product, on_delete=models.CASCADE,blank=True, null=True)
    quantity = models.IntegerField(default=1)


    def __str__(self):
        return f"{self.quantity} of {self.item.name}"

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
    items = models.ManyToManyField(OrderItem,blank=True, null=True)
    start_date = models.DateTimeField(auto_now_add=True)
    ordered_date = models.DateTimeField()
    ordered = models.BooleanField(default=False)

    def __str__(self):
        return self.user.email

My views:

@login_required
def add_to_cart(self, pk):
    item = get_object_or_404(Product, pk=pk)
    order_item, created = OrderItem.objects.get_or_create(
        item=item,
        user=self.request.user,
        ordered=False
    )
    order_qs = Order.objects.filter(user=self.request.user, ordered=False)

    if order_qs.exists():
        order = order_qs[0]

        if order.items.filter(item__pk=item.pk).exists():
            order_item.quantity += 1
            order_item.save()
            return Response({"message": "Added quantity Item", },
                            status=status.HTTP_200_OK
                            )
        else:
            order.items.add(order_item)
            return Response({"message": " Item added to your cart", },
                            status=status.HTTP_200_OK,
                            )
    else:
        ordered_date = datetime.timezone.now()
        order = Order.objects.create(user=self.request.user, ordered_date=ordered_date)
        order.items.add(order_item)
        return Response({"message": "Item added to your cart", },
                        status=status.HTTP_200_OK,
                        )

My url:

path('api/addorderitem/int:pk', views.add_to_cart, name='api-addorder'),

The following code is using APIView:

class AddtoOrderItemView(ListCreateAPIView):
     permission_classes = [IsAuthenticated]
     queryset = OrderItem.objects.all()
     serializer_class = OrderItemSerializer
     def post(self,request,*args,**kwargs)
      """same code as abvoe""

Here post fucntion doesnt take pk, but I have pk in my code which is unrecognized. So, I am not sure what to do because we cant use def add_to_cart(self, pk) in ListCreateAPIView.

My serializers:

class OrderItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = ['id','user','ordered','item', 'quantity']
        depth = 1

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

Solution

  • Finally, I am able to add items to the cart using APIView. APIView is a base class where we can override any custom functions(post, get, etc) according to the needs and business logic.

    Here is my view, which works.

    class AddtoOrderItemView(APIView):
        permission_classes = [IsAuthenticated]
        # queryset = OrderItem.objects.all()
        # serializer_class = OrderItemSerializer
        # @action(detail=True, methods=['post'])
    # @login_required
        def post(self, request, pk):
            item = get_object_or_404(Product, pk=pk)
            order_item, created = OrderItem.objects.get_or_create(
                item=item,
                user=self.request.user,
                ordered=False
            )
            order_qs = Order.objects.filter(user=self.request.user, ordered=False)
    
            if order_qs.exists():
                order = order_qs[0]
    
                if order.items.filter(item__pk=item.pk).exists():
                    order_item.quantity += 1
                    order_item.save()
                    return Response({"message": "Quantity is added",
                                     },
                                    status=status.HTTP_200_OK
                                    )
                else:
                    order.items.add(order_item)
                    return Response({"message": " Item added to your cart", },
                                    status=status.HTTP_200_OK,
                                    )
            else:
                ordered_date = datetime.now()
                order = Order.objects.create(user=self.request.user, ordered_date=ordered_date)
                order.items.add(order_item)
                return Response({"message": "Order is created & Item added to your cart", },
                                status=status.HTTP_200_OK,
                                )
    

    Here I override post function using (self,request,pk) as the parameters as they were required. It is not a standard way of overriding a post function but we can write in that way inside APIView.