Django REST Framework - ListSerializer - Actualizaciones Múltiples

 Se muestra un ejemplo, de como realizar la implementación de Múltiples actualizaciones en una sola petición , es decir enviando una lista de objetos, y usando la clase ListSerializer realizamos las actualizaciones (inserciones u eliminaciones).




El modelo para el ejemplo





La Vista

    def post(selfrequest):
        """ Ejemplo de manejo de listas en Serializer

         
          Para este ejemplo asumimos lo siguiente:
          Se tienen que enviar todos los datos existentes de los empleados en el JSON ya que
          se comparara con la base de datos y :
           1.- Si se encuentran se actualizan los datos,
           2.- Si no existen en la base de datos  se crean,
           3.- Si se encuentran en la base de datos, pero no fueron pasados en el JSON se elimnan.

         """

        # Obtener el  JSON.
        data = request.data

        # Obtener los datos de la base de datos        
        emp = Employes.objects.all()
        #Es necesario pasarlo a listas
        _arr_emp = [entry for entry in emp]

        # Serializar los datos
        se = serializers.AddListEmployesSerializer(instance=_arr_empdata = datamany = True)
        

        #validar y guardar
        if se.is_valid():            
            se.save()
            payload = {
                'codigo'status.HTTP_200_OK,
                 'mensaje''Ok',  
                 'data'se.data 
            }
        else:
            payload = {
                'codigo'status.HTTP_400_BAD_REQUEST
                'mensaje''Fallo',  
                'data'se.errors
            }   

        return Response(payloadstatus=status.HTTP_200_OK);


El Objeto Serailizer AddListEmployesSerializer es de tipo ModelSerializer, 

class AddListEmployesSerializer(serializers.ModelSerializer):
    employeid = serializers.IntegerField()

    class Meta:
        #list_serializer_class , nos sirve para trabajar con varios objetos
        #en forma de listas, util para Insert, Update, Delete
        list_serializer_class = UpdateEmployesSerializer  
        model = Employes
        fields = '__all__'

y este a su vez implementa de una clase ListSerializer, para ello se modifica el serializar usando la clase list_serializer_class 



El atributo employeid = serializers.IntegerField() es requerido (la documentación sugiere usar la clave primaria), para poder crear una clave del diccionario que se creara en la clase UpdateEmployesSerializer .



class UpdateEmployesSerializer(serializers.ListSerializer):
    """ Recibe dos listas para comparar los datos """

    class Meta:
        model = Employes
        fields = '__all__'


    def update(selfinstancevalidated_data):        

        #instance = valor original (de la bd)
        #validated_data = valor a comparar
        mapping = {emp.employeid: emp for emp in instance}
        data_mapping = {item['employeid']: item for item in validated_data}
        
        # Realizamos las creaciones si no se encuentran en data_mapping,
        # y las actualizaciones si se encuentran keys en data_mapping
        ret = []
        for _iddata in data_mapping.items():
            emp = mapping.get(_idNone)            
            if emp is None:                
                ret.append(self.child.create(data))  #Si no se encuentra se crea
            else:                
                ret.append(self.child.update(empdata)) #Se se encuentra se actualiza

        # Realizamos las eliminaciones, si no se encuentra en data_mapping
        for _iddata in mapping.items():
            if _id not in data_mapping:
                data.delete()

        return ret

En la implementación de la clase  UpdateEmployesSerializer , pasamos dos listas, la lista de valores enviados en el request del JSON, y comparando con la lista de valores de la base de datos:

1.- Si los datos JSON vs BD no se encuentran se crean

2.- Si en el JSON vs BD se encuentran se actuliza

3.- Si en la BD Vs JSON no se encuentran datos, se eliminan de la BD.


Para consumir, pasar en el body de la petición  la lista de valores  (Para el ejemplo usamos  POST)



Con esto ya se puede consumir la appi. 

Espero les sea de utilidad


Versiones

  • Django  3.2.3
  • djangorestframework 3.12.4
  • Python 3.9.5 


Descargar Código








Comentarios

Entradas populares de este blog

Django. [Errno 10013] Intento de Acceso a un Socket no Permitido por sus permisos de acceso.

Crystal Reports para VS2010. El Texto Restante no parece se parte de la Formula.

ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)