1

I have following model:

class Device(models.Model):
    #more_code
    supplier = models.ForeignKey(
        Supplier, on_delete=SET_NULL, blank=True, null=True, related_name="devices"
    )

I need a Patch endpoint to change the supplier from a Device. Everything in the view looks to work, only the device.save() doesn't update the state of the object

This is my view:

def patch(self, request, site_pk):
    """
    PATCH the device's supplier info of the site.
    """
    all_device_token = False
    if request.data.get("device") == "ALL":
        all_device_token = True
        arguments = {}
    else:
        device_pk = request.data.get("device")
        arguments = {"id": device_pk}

    devices = Device.objects.filter(site_id=site_pk, **arguments).all()
    if not devices.exists():
        raise PermissionDenied("The device does not belong to the site.")

    if all_device_token:
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(
            devices, many=True, data=request.data, partial=True,
        )
        serializer.is_valid(raise_exception=True)
        new_supplier = get_object_or_404(Supplier, pk=request.data.get("supplier"))
        for device in devices:
            device.supplier.id = new_supplier.pk
            device.supplier.name = new_supplier.name
            device.save()
    else:
        device = devices.first()

        serializer_class = self.get_serializer_class()
        serializer = serializer_class(device, data=request.data, partial=True,)
        serializer.is_valid(raise_exception=True)

        if "supplier" in self.request.data:
            new_supplier = serializer.validated_data["supplier"]
            device.supplier.id = new_supplier.pk
            device.supplier.name = new_supplier.name
            device.save()

        # serializer.save()
    return Response(serializer.data, status=status.HTTP_200_OK)

My serialiser is returning the correct info to. Do I see something overhead?

1
  • You should not device.save(), but device.supplier.save(), since that is the object you are updating. That being said, you should not change the primary key. Just create a new Supplier (with the new content), and let your devices refer to that one. Commented Mar 23, 2020 at 19:45

1 Answer 1

1

You here update the supplier object with a new primary key, and a new name:

new_supplier = get_object_or_404(Supplier, pk=request.data.get('supplier'))
for device in devices:
    device.supplier.id = new_supplier.pk
    device.supplier.name = new_supplier.name
    device.save()

I however strongly advise not to change the primary key of the old supplier (nor duplicate data). If you do that, you should save the device.supplier.save(), since you updated that object.

But it is not good practice to do this, since then you change that Supplier object whereas, you do not want to change the name of the old supplier, you want to link the device to a new Supplier. You can do that by setting the supplier_id foreign key, and save the device:

supplier_id = request.data.get('supplier')
for device in devices:
    device.supplier_id = supplier_id
    device.save()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.