3.0: How to pass arguments to instance.save()?

3,289 views
Skip to first unread message

David Fischer

unread,
Nov 21, 2014, 9:30:30 AM11/21/14
to django-res...@googlegroups.com
Hello,

I am using a Model mixin that calls obj.full_clean() by obj.save(). Because DRF already validate the data before it is saved in database it means this call is redundant. So I implemented a Serializer mixin that overrides save_object(self, obj, **kwargs) and modify kwargs.

What is the cleanest way to do the same in DRF 3.0?

I thought I may override update(self, instance, validated_attrs) and patch the method instance.save before calling super().update(...). However I also remarked that the serializer is using model manager .create(). I probably will have to adapt my mixins...



Thanks for your work and your time.

Regards,

David Fischer

Tom Christie

unread,
Nov 21, 2014, 9:37:23 AM11/21/14
to django-res...@googlegroups.com
Not sure I understand the question exactly right, but you can pass extra keyword arguments to `.save()` on the serializer instance.

A reusable serializer class (or mixin) might override `.save()` to add in a keyword argument by default.

Eg.

    def save(self, **kwargs):
        kwargs['validated'] = False
        super(ThisClassName, self).save(**kwargs)

Hope that helps?

David Fischer

unread,
Nov 21, 2014, 9:51:07 AM11/21/14
to django-res...@googlegroups.com
The serializer class method save() delegate the call of instance.save() to serializer.update() and the call of model.objects.create() to serializer.create(). It means I have to override both methods.

In Django, the forms save methods has a argument commit=True to allows developers to override it and call instance.save() in their own code. This can be a nice improvement for serializer.update().

However it still remains serializer.create() ...

Thanks for your quick answer!

Tom Christie

unread,
Nov 21, 2014, 10:18:48 AM11/21/14
to django-res...@googlegroups.com
Oh right, you want to override how the *model* `.save()` is called?

Yes you'd need to override both `.create()` and `.update()`.

For `create()` you'd want to clone the default method but instantiate and then save the instance, rather than using `ModelClass.objects.create()`.


> In Django, the forms save methods has a argument commit=True to allows developers to override it and call instance.save() in their own code.

Instantiating and returning an unsaved model instance isn't something I want the serializer API to provide for.
If you really want to do something like that, just take the .validated_data off the serializer and use that directly.

This blogpost gives some context on that... http://www.dabapps.com/blog/django-models-and-encapsulation/

Personally if you *really do* want to add in some validation that runs during the object save, I'd just always have it run, and raise hard assertion errors if it fails.
(I'm not clear if you're expecting to handle those 'ValidationErrors' or not, but generally validation should always run pre-save, not during save.)

Cheers,

  Tom
Reply all
Reply to author
Forward
0 new messages