Skip to content

View pre_save called before model clean #729

joaomsa opened this Issue Mar 13, 2013 · 7 comments

4 participants

joaomsa commented Mar 13, 2013

In my model I test some constraints that rely on field that's added by the ListCreateAPIView's pre_save method, however since the models's clean method is called before it, I get a DoesNotExist exception when I try to access self.owner. Is this the indented order?

class Car(models.Model):
    owner = models.ForeignKey('auth.User', related_name='cars')

    def clean(self, *args, **kwargs):
        super(Car, self).clean(*args, **kwargs)

        print('called clean')
        querySet = self.__class__._default_manager.filter(owner=self.owner)
class CarList(generics.ListCreateAPIView):
    def pre_save(self, obj):
        print('called pre_save')
        obj.owner = self.request.user

Can see the issue yup, but I'm not sure what'd be a good we to resolve it.
At the moment the object isn't available on the serializer until after .is_valid() has been called, so you can't call pre_save until after that's happened.

ameyc commented Jan 15, 2014

Was this ever resolved?


@asc89 Nope. It might be useful to have someone rephrase the problem they are seeing - this ticket always confuses me a little.

ameyc commented Jan 15, 2014

I'm running into something very similar to this ticket. In our Django model's clean() method we're accessing a field (owner)that is being set in the pre_save() method of the ModelViewSet. This leads to a DoesNotExist exception in the clean(). Is there any other hook (other than overriding the create(), where I could be setting the owner by pulling it from the request so that it is there when clean() gets called?


I worked around this problem by overriding restore_fields and restore_object in my ModelSerializer subclass.

If you have an owner model in the request, you'd do something like this:

class OwnedModelSerializer(serializers.ModelSerializer):
    def restore_fields(self, data, files):
        owner = self.context['request'].owner

        if data and not 'owner' in data:
            Make sure owner is available in data, in case the owner attribute is NOT an excluded field.
            d = data.copy()
            d['owner'] =
            data = d

        reverted_data = super(OwnedModelSerializer, self).restore_fields(data, files)

        if not 'owner' in reverted_data:
            Owner field is excluded, and thus ignored by restore_fields.
            Let's force it to be present anyway.
            reverted_data['owner'] = owner

        return reverted_data

    def restore_object(self, attrs, instance=None):
        The attrs parameter is basically the reverted_data returned by restore_fields.
        ret = super(OwnedModelSerializer, self).restore_object(attrs, instance)

        if ret == attrs:  # I think this is true in case of errors, not sure
            return attrs

        ret.owner = attrs['owner']

        return ret
@tomchristie tomchristie added this to the 3.0 Release milestone Aug 18, 2014

Hoping the 3.0 redesign will help resolve this, as the serializer changes will also affect the default pre_save implementation.


Closing pending 3.0 - feel free to reopen if it does not resolve the issue.
Also marking this with the Serializer to ensure it gets a further review prior to release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.