Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I need to attach a user to a request, this seems like a fairly common thing to need to do, but it's turning out to be damn near impossible.

The docs for the Django REST Framework suggest using the pre_save method of the serializer class, which I did, but it doesn't get called when serializer.is_valid() is called, which makes it kind of worthless since without the user field the serializer fails validation.

I've seen a few suggestions but they seem like crazy hacks and/or don't work. Plus, I feel like this is way too common of a task to really need all the stuff I see people suggesting. I can't be the only person to need to attach a user to a object created in a REST request.

like image 878
jmickela Avatar asked Nov 15 '13 05:11

jmickela


2 Answers

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)
like image 192
Nino Walker Avatar answered Sep 21 '22 05:09

Nino Walker


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.

like image 41
Kevin Stone Avatar answered Sep 17 '22 05:09

Kevin Stone