Search code examples
djangodjango-rest-frameworkdjango-viewsdjango-serializer

How to update multiple objects in django rest framework?


I am trying to update multiple objects using IDs which i am passing in every objects that need to be updated but can't find any way to do it successfully. Here is my code

models.py

class EventTicket(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid_generate_v1mc, editable=False)
    name = models.CharField(max_length=250)
    description = models.TextField(max_length=1000)

views.py

  class EventTicketView(APIView, PaginationHandlerMixin):
        permission_classes = (AllowAny,)
        def get_object(self, ticket_id):
            try:
                return EventTicket.objects.get(id=ticket_id)
            except EventTicket.DoesNotExist():
                raise status.HTTP_400_BAD_REQUEST
        def patch(self, request, *args, **kwargs):
            for each_ticket in request.data:

                ticket_id = self.get_object(each_ticket['ticket_id'])

                serializer = EventTicketSerializer(instance=ticket_id,data=request.data,partial=True)
                if serializer.is_valid():
                    serializer.save()
                    result = {
                        'message': "updated sucessfully"
                    }
                    return Response(result, status=status.HTTP_201_CREATED)
                else:
                    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py

class EventTicketSerializer(serializers.ModelSerializer):
    class Meta:
        model = EventTicket
        fields = ['name', 'description']
```

I have to send data like list of multiple objects :::
[
    {
    "ticket_id": "054665ea-4fde-11ea-94b2-9f415c43ba4c",    
    "name": "chris",
    "description":"The golden ticket for day only",

    },
    {   
    "ticket_id": "054656ea-4fde-11ea-94b2-9f415c43ba4c",
    "name": "daut",
    "description":"The premium ticket for day only",

    }
]

Solution

  • The following code will give you a proper understanding of updating multiple objects in single request. For updating multiple objects in a single request it is best practice to use the PUT method instead of PATCH. Here, the body data given is:

    {
        "ids":[
            "5e41770d2e8fa013d1f034ec",
            "5e41772c2e8fa013d1f034ee",
            "5e4177702e8fa013d1f034f2",
            "5e453f302e8fa075aa18b277",
            "5e4a314f2e8fa070c5251a0a"
        ]
    }
    

    I'm updating the enabled attribute from False to True for given ids of DemoConfig model. In the same way, you can update your data. As per your requirement, you can write validate methods to validate the body data. Serializer is written to serialize the instance data for the response.

    class DemoAPI(APIView):
    
        def get_object(self, obj_id):
            try:
                return DemoConfig.objects.get(id=obj_id)
            except (DemoConfig.DoesNotExist, ValidationError):
                raise status.HTTP_400_BAD_REQUEST
        
        def validate_ids(self, id_list):
            for id in id_list:
                try:
                    DemoConfig.objects.get(id=id)
                except (DemoConfig.DoesNotExist, ValidationError):
                    raise status.HTTP_400_BAD_REQUEST
            return True
    
        def put(self, request, *args, **kwargs):
            id_list = request.data['ids']
            self.validate_ids(id_list=id_list)
            instances = []
            for id in id_list:
                obj = self.get_object(obj_id=id)
                obj.enabled = True
                obj.save()
                instances.append(obj)
            serializer = DemoSerializer(instances, many=True)
            return Response(serializer.data)
    

    Serialiser for this view is:

    class DemoSerializer(DocumentSerializer):
        class Meta:
            model = DemoConfig
            fields = '__all__'
    
    

    Output:

    {
      "data": [
        {
          "id": "5e41770d2e8fa013d1f034ec",
          "name": "CONFIG_1",
          "enabled": true,
          
        },
        {
          "id": "5e41772c2e8fa013d1f034ee",
          "name": "CONFIG_2",
          "enabled": true,
          
        },
        {
          "id": "5e4177702e8fa013d1f034f2",
          "name": "CONFIG_3",
          "enabled": true,
          
        },
        {
          "id": "5e453f302e8fa075aa18b277",
          "name": "CONFIG_4",
          "enabled": true,
          
        },
        {
          "id": "5e4a314f2e8fa070c5251a0a",
          "name": "CONFIG_5",
          "enabled": true,
          
        }
      ]
    }
    

    As per your code requirement, you need to use PUT method in the following way.

        def put(self, request, *args, **kwargs):
            data = request.data
            ticket_ids = [i['ticket_id'] for i in data]
            self.validate_ids(ticket_ids)
            instances = []
            for temp_dict in data:
                ticket_id = temp_dict['ticket_id']
                name = temp_dict['name']
                description = temp_dict['description']
                obj = self.get_object(ticket_id)
                obj.name = name
                obj.description = description
                obj.save()
                instances.append(obj)
            serializer = DemoSerializer(instances, many=True)
            return Response(serializer.data)