iuuujkl
iuuujkl

Reputation: 2384

PATCH (partial=true) doesn't work in Django

I have a PATCH endpoint to change some non required data for a "Site". Through the endpoint you should be able to edit the description and supplier from a Site. The description is already working on the existing project. When I try to add the supplier to the PATCH, it doesn't update it..

View:

class AdminSiteDetailView(GenericAPIView):
    def get_permissions(self):
        return IsAuthenticated(),

    def get_serializer_class(self):
        return AdminSiteDetailSerializer

    @swagger_auto_schema(
        responses={
            200: openapi.Response(
                _("Successfully"),
                AdminSiteDetailSerializer,
            )
        }
    )
    def get(self, request, site_pk):
        """
        GET the data from the site.
        """
        #somecode

    @swagger_auto_schema(
        responses={
            200: openapi.Response(
                _("Successfully"),
                AdminSiteDetailSerializer,
            )
        }
    )
    def patch(self, request, site_pk):
        """
        PATCH the description of the site.
        """

        site = get_object_or_404(Site, pk=site_pk)
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(site, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        site.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

Serializer:

class AdminSiteSerializer(serializers.ModelSerializer):
    supplier = serializers.SerializerMethodField()

    class Meta:
        model = Site
        fields = [
            "id",
            "name",
            "supplier",
        ]

    @staticmethod
    def get_supplier(site):
        if not site.supplier:
            return None
        return SupplierSerializer(site.supplier).data


class AdminSiteDetailSerializer(AdminSiteSerializer):
    class Meta(AdminSiteSerializer.Meta):
        fields = AdminSiteSerializer.Meta.fields + ["description"]


class SupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = ("id", "name")

model:

class Site(models.Model):
    class Meta:
        ordering = ("name",)

    name = models.CharField(max_length=250)
    description = models.TextField(blank=True, null=True)
    supplier = models.ForeignKey(
        Supplier, on_delete=SET_NULL, blank=True, null=True, related_name="sites"
    )

Upvotes: 1

Views: 164

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47364

SerializerMethodField is read-only field. So you cannot use it to update data. Instead of using it in your case you can override serializer's to_representation method:

class AdminSiteSerializer(serializers.ModelSerializer):

    class Meta:
        model = Site
        fields = [
            "id",
            "name",
            "supplier",
        ]


    def to_representation(self, instance):
        data = super().to_representation(instance)   
        if not instance.supplier:
            data['supplier'] = None
        data['supplier'] = SupplierSerializer(site.supplier).data
        return data

Upvotes: 1

Related Questions