Django REST - PUT and PATCH create new object instead of updating

Viewed 423

I'm creating a basic Django REST API that will work with a catalogue of products. I have to check every time a non-registered user GETS a product and add to the current value. And the GET and DELETE work perfectly fine. The problem is that whenever I want to update a product, a new Product is created instead.

I have 2 models:

class Brand(models.Model):
    brand_name = models.CharField(max_length=500)
    def __str__(self):
        return self.brand_name

class Product(models.Model):
    sku = models.PositiveIntegerField(primary_key=True, validators=[MaxValueValidator(999999999999999)])
    product_name = models.CharField(max_length=500)
    product_price = models.DecimalField( max_digits=50, decimal_places=2)
    product_brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    times_searched_anonymous = models.PositiveIntegerField(default=0)


    def __str__ (self):
        return self.product_name + ' (' + self.product_brand.brand_name + ')' + ' - $' + str(self.product_price)

These are my serializers:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = [
            "sku",
            "product_name",
            "product_price",
            "product_brand",
            "times_searched_anonymous"
        ]


class BrandSerializer(serializers.ModelSerializer):
    class Meta:
        model = Brand
        fields = [
            "brand_name",
            "pk",
        ]

And this is the view I have:

class ProductDetail(generics.RetrieveUpdateDestroyAPIView):
    """
       Retrieve, update or delete a product instance.
    """

    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get_object(self, pk):
        try:
            return Product.objects.get(pk=pk)
        except Product.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        product = self.get_object(pk)
        serializer = ProductSerializer(product)
        if not request.user.is_authenticated:
            data2 = {'times_searched_anonymous': product.times_searched_anonymous + 1}
            serializer2 = ProductSerializer(product, data=data2, partial=True)
            if serializer2.is_valid():
                serializer2.save()
                return Response(serializer2.data)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        product = self.get_object(pk)
        serializer = ProductSerializer(product, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
           return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def patch(self, request, pk):
        product = self.get_object(pk)
        serializer = ProductSerializer(product, data=request.data,
                                       partial=True)  # set partial=True to update a data partially
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(code=201, data=serializer.data)
        return JsonResponse(code=400, data="wrong parameters")

    def delete(self, request, pk, format=None):
        product = self.get_object(pk)
        product.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Thougths?

1 Answers

in put method change line

 serializer = ProductSerializer(product, data=request.data, partial=True)

to be serializer = ProductSerializer(instance=product, data=request.data, partial=False)

also in patch method change line

serializer = ProductSerializer(product, data=request.data, partial=True)

to be

 serializer = ProductSerializer(instance=product, data=request.data, partial=False)
Related