Tengo curiosidad si hay una manera de ver lo que tienecambiado en un objeto después de guardarlo utilizando el marco de descanso de Django. Tengo algún comportamiento especial que necesito para comprobar si un campo ha sido cambiado de su valor original que esperaba manejar usando el post_save
en generics.RetrieveUpdateDestroyAPIView
.
Mi primer pensamiento fue comprobar usando pre_save
pero parece que pre_save
El argumento del objeto s ya tiene los cambios aplicados.
Respuestas
10 por respuesta № 1ANTIGUA RESPUESTA para django resto framework versión 2.3.12:
Para comprobar si algo ha cambiado en la actualización, tendrá que comparar la instancia del modelo sin cambios que es self.object con la instancia del modelo modificado que es serializer.object.
El argumento objeto que se pasa al método pre_save es el serializer.object que aún no se ha guardado en la base de datos con los nuevos cambios.
La instancia del modelo sin cambios es el self.object que se ha recuperado de la base de datos mediante self.get_object_or_none (). Compárelo con el argumento obj en el método pre_save.
def pre_save(self,obj):
unchanged_instance = self.object
changed_instance = obj
..... # comparison code
NUEVA RESPUESTA para django resto framework 3.3:
pre_save y post_save ya no son válidos http://www.django-rest-framework.org/topics/3.0-announcement/#generic-views
Ahora puede colocar cualquier lógica de guardado previo o guardado en el método perform_update. Por ejemplo:
def perform_update(self, serializer):
old_obj = self.get_object()
new_data_dict = serializer.validated_data
# pre save logic
if old_obj.name != new_data_dict["name"]
do_smething
.....
serializer.save()
# post save logic
......
1 para la respuesta № 2
Pude hacer esto con la ayuda de model_utils FieldTracker. Puede instalar un rastreador en el modelo relevante, luego en pre_save
(por post_save
es demasiado tarde) puedes hacer esto:
def pre_save(self, obj):
if hasattr(obj, "tracker"):
self.changed_fields = obj.tracker.changed()
else:
self.changed_fields = None
changed_fields
se verá así: {"is_public": False, "desc": None}