Вопрос

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.

Now you can place any pre save or post save logic in perform_update method. For example:

def perform_update(self, serializer):
    # NOTE: serializer.instance gets updated after calling save
    # if you want to use the old_obj after saving the serializer you should
    # use self.get_object() to get the old instance. 
    # other wise serializer.instance would do fine
    old_obj = self.get_object()
    new_data_dict = serializer.validated_data
    # pre save logic
    if old_obj.name != new_data_dict['name']:
        do_something
    .....
    new_obj = 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}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top