I am curious if there is a way to see what has changed on an object after saving it using the Django Rest Framework. I have some special behavior I need to check if a field has been changed from its original value that I was hoping to handle using the post_save
on generics.RetrieveUpdateDestroyAPIView
.
My first thought was to check using pre_save
but it seems that pre_save
's object argument already has the changes applied to it.
OLD ANSWER for django rest framework version 2.3.12:
To check if anything has changed on update, you will have to compare the unchanged model instance which is self.object with the changed model instance which is serializer.object.
The object argument which is passed to the pre_save method is the serializer.object which is not yet saved in the database with the new changes.
The unchanged model instance is the self.object which has been fetched from the database using self.get_object_or_none(). Compare it with the obj argument in the pre_save method.
def pre_save(self,obj):
unchanged_instance = self.object
changed_instance = obj
..... # comparison code
NEW ANSWER for django rest framework 3.3:
pre_save and post_save are no longer valid
http://www.django-rest-framework.org/topics/3.0-announcement/#generic-views
Now you can place any pre save or post save logic in perform_update method. For example:
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
......
I was able to do this with help from model_utils FieldTracker. You can install a tracker on the relevant model, then in pre_save
(by post_save
it's too late) you can do this:
def pre_save(self, obj):
if hasattr(obj, 'tracker'):
self.changed_fields = obj.tracker.changed()
else:
self.changed_fields = None
changed_fields
will look like this: {'is_public': False, 'desc': None}