[Solved]-Django REST Framework, pre_save() and serializer.is_valid(), how do they work?

2👍

It turned out the problem was that I was using ListAPIView as the base class for my view class and it doesn’t have the pre_save method defined. When I added some of the mixins which had it defined everything started working.

Seems weird that something used in a lot of the basic tutorials doesn’t support such a basic feature, but live and learn.

5👍

Assuming you’re using one of the Authentication mechanisms described here (or Django Auth):

http://django-rest-framework.org/api-guide/authentication.html, you have a

request.user object.

When you create the serializer, pull it out of the request/pass it in when you instantiate.

MySerializer(data={"user": request.user, "otherField"=... })

If you are doing:

MySerializer(data=request.DATA)

You’ll need to copy the request.DATA object:

from django.utils.datastructures import MultiValueDict
...
data = MultiValueDict(request.DATA)
data['user'] = request.user
MySerializer(data=data)

4👍

pre_save is called after is_valid but before the instance is saved to the database. You need to override the validation (using def get_validation_exclusions(self): on that user serializer field since you’ll fix the validation issue in pre_save. See my previous answer here:

Django REST Framework serializer field required=false

I raised it up to the authors of DRF and they’re going to investigating a more workable solution.

1👍

The best solution to this problem is to mark required fields that are populated in pre_save as read_only_fields in the serializer.

To do that, add the following to the serializer class:

class MySerializer(serializers.ModelSerializer):
    ...
    class Meta:
        ...
        read_only_fields = ['user', 'my_other_field', ...]

1👍

In the new versions of DRF (3.x), pre_save was replaced by
perform_create and perform_update:
Reference

Leave a comment