v.thorey
v.thorey

Reputation: 2087

django rest add data to serializer when saving

I want to do the following:

models.py

class MyModel(TimeStampedModel, models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)

serializers.py

class MyModelSerializerCreate(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = (
            'name',
        )

And I would like to add as owner the current user in request.user. Currently I am adding this in my view directly by uptading request.data with user and then pass the updated data to my serializer.

    data = request.data
    # Add owner to data
    data["owner"] = request.user.pk
    serializer = self.get_serializer(data=data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)

I would like to do this in my serializer directly but can't find a way to properly do it because it looks like data validation to me. Is this a good idea ? Should I keep this logic in my views or move it to my serializer ?

Upvotes: 10

Views: 19019

Answers (3)

Ivan Semochkin
Ivan Semochkin

Reputation: 8897

You can get a user from serializer context:

self.context['request'].user
It is passed from a method get_serializer_context which originally created in a GenericAPIView:

class GenericAPIView(APIView):
    ....
    def get_serializer_context(self):
        """
        Extra context provided to the serializer class.
        """
        return {
            'request': self.request,
            'format': self.format_kwarg,
            'view': self
        }  

Inside a serializer you need to override a create method:

class MyModelSerializerCreate(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = ('name', )
 
    def create(self, validated_data):
        validated_data['owner'] = self.context['request'].user
        return super(MyModelSerializerCreate, self).create(validated_data)

You could also override an update and delete methods if you need some special interactions with the User model.

Upvotes: 22

Menda
Menda

Reputation: 1813

The solution from Ivan Semochkin did not work for me, as it never entered into the create() method of the serializer. As request.data field is immutable, you need to copy it and then extend it.

from django.http import HttpRequest
from rest_framework.request import Request

class MyModelViewSet(ModelViewSet):
    def _extend_request(self, request):
        data = request.POST.copy()
        data['owner'] = request.user
        request_extended = Request(HttpRequest())
        request_extended._full_data = data

    def create(self, request, *args, **kwargs):
        request_extended = self._extend_request(request)
        return super().create(request_extended, *args, **kwargs)

Upvotes: 2

Chris Shaw
Chris Shaw

Reputation: 99

Unfortunatly I dont have the reputation points to comment on @ivan-Semochkin post above, but should the last line not be:

return super(MyModelSerializerCreate, self).create(validated_data)

Upvotes: 4

Related Questions