Skip to content

The Serializer data accessor returns cached and stale _data after .update() #2532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dennisschaaf opened this issue Feb 9, 2015 · 1 comment

Comments

@dennisschaaf
Copy link

Hey,

I am having a problem with the way _data is cached. We are using the RetrieveUpdateView to update a model with a nested list. The result of the operation is that the database is updated, but the old object is being returned.

The UpdateModelMixin performs an update on the following Serializer:

class MixDesignCreateSerializer(ModelSerializer):
  expiration_date = DateField(format=DATE_FORMAT, input_formats=(DATE_FORMAT,), required=False, )
components = MixComponentSerializer(many=True, required=False)

  def update(self, instance, validated_data):
    # Update nested list
    extracted_components = validated_data.pop('components')
    instance.components = self['components'].update(instance.components, extracted_components)

    instance = super(MixDesignCreateSerializer, self).update(instance, validated_data)

    # The instance is now properly updated in the DB
    # but self._data still contains a cache of the
    # initial _data created during is_valid()

    # The only 'hack' is to delete _data, whilch will
    # force a fetch from the database
    delattr(self, '_data')
    self.is_valid()

    return instance

and then renders the result of serializer.data

@dennisschaaf dennisschaaf changed the title The Serializer data accessor returns cashed and stale _data after .update() The Serializer data accessor returns cached and stale _data after .update() Feb 9, 2015
@tomchristie
Copy link
Member

_data is private API, so it's unclear why you're needing to access it.
Use initial_data to see the passed data, and .validated_data after calling .is_valid().

Additionally calling is_valid() inside update() as you're doing doesn't make sense - the validation
should always happen before calling .save() and triggering an update or create.

It's possible that we could add some extra assertions to prevent this type of usage, but I'd need to see a simpler example before I'd be convinced exactly what we'd want to guard against.

I'd suggest describing what you're trying to do on the mailing list and finding a more correct way to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants