Manera eficiente de actualizar múltiples campos del objeto modelo Django

Estoy tratando de actualizar el usuario en la base de datos Django.

Los datos obtenidos son los siguientes:

fetched_data = { 'id': 1, 'first_name': 'John', 'last_name': 'Doe', 'phone': '+32 12', 'mobile_phone': '+32 13', 'email': 'myemail@hotmail.com', 'username': 'myusername' } 

Me sale el usuario con este id de la siguiente manera:

 old_user = User.objects.get(pk=fetched_data['id']) 

Si actualizo al usuario como sigue:

 old_user.username = fetched_data['username'] old_user.first_name = fetched_data['first_name'] ...... old_user.save() 

funciona bien, pero no quiero hacerlo para todos los registros, así que intenté algo como:

 for fetched_data_key in fetched_data: old_user.fetched_data_key = fetched_data['fetched_data_key'] //old_user[fetched_data_key] = fetched_data['fetched_data_key'] --- I tried this way to old_user.save() 

Pero eso no funciona. ¿Alguna idea de cómo puedo actualizar al usuario sin hacerlo para cada registro?

Puede actualizar una fila en la base de datos sin recuperarla y deserializarla; update() puede hacerlo. P.ej:

 User.objects.filter(id=data['id']).update(email=data['email'], phone=data['phone']) 

Esto emitirá una statement de update SQL y es mucho más rápido que el código en su publicación. Nunca recuperará los datos ni perderá tiempo creando un objeto User .

Sin embargo, no puede enviar una gran cantidad de datos de actualización a la base de datos SQL y pedirle que los asigne a diferentes filas de una sola vez. Si necesita una actualización masiva como esa realizada muy rápidamente, su mejor apuesta es probablemente insertar los datos en una tabla separada y luego actualizarlos para select en esa tabla . Django ORM no admite esto, por lo que puedo decir.

Aún más simple si usa el método .update() del objeto QuerySet como:

 my_id = fetched_data.pop('id') # remove 'id' from `fetch_data` # as it is not supposed to be updated User.objects.filter(pk=my_id).update(**fetched_data) # unpack the content of `dict` ^ 

fetched_data el contenido de fetched_data dict y actualizará los registros en el objeto User cuyas columnas están presentes como clave para el fetched_data . Dado que está llamando a filter en pk , siempre devolverá un registro único.

 setattr(old_user, fetched_data_key, fetched_data['fetched_data_key']) 

Si usa .update entonces hay un problema, ya que no boostá la señal post_save o pre_save , así que si desea usar cualquier señal en cualquier cambio de datos, entonces User.objects.filter(pk=fetched_data['id']).update(**kwargs) no funcionará.

Así que puedes usar setattr() para actualizar los campos y luego .save guardaría la fila que actualizaría la fila también generaría una señal.

 old_user = User.objects.get(pk=fetched_data['id']) for key, value in fetched_data.iteritems(): setattr(old_user, key, value) old_user.save()