J. Hesters
J. Hesters

Reputation: 14814

Django Rest: Add data to a "required" field automatically

I want to automatically assign a value for a required field in Django Rest framework, without the value having to be given in the post request.

My View:

class WaitercallCreate(CreateAPIView):
    serializer_class = WaitercallCreateSerializer
    permission_classes = (IsAuthenticated, )

The Serializer:

class WaitercallCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Waitercall
        fields = ('order', 'user', 'done', 'type_of_call')

    read_only_fields = ('user', 'done')

Users should be able to do a postrequest, only giving their token in the header and the order id as the body. I want to set the value for user by default to the requests user. I tried overwriting the perform_create method in my view like this:

def perform_create(self, serializer):
        serializer.save(user=self.request.user)

This didn't work. Then I tried overwriting the create method in the view like this:

def create(self, request, *args, **kwargs):
        data = request.data
        data['user'] = request.user
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Which also didn't work, because Orderdicts are immutable. For the first (and the last try, read further) I always get the same response:

{
    "user": [
        "This field is required."
    ]
}

Lastly I found this stackoverflow post, which recommends overwriting the create method in the serializer. Like this:

def create(self, validated_data):
    print(self.context['request'].user)
    validated_data['user'] = self.context['request'].user
    return super(WaitercallCreateSerializer, self).create(validated_data)

It also gave me the same response. I'm lost. What can I try next?

Upvotes: 1

Views: 1805

Answers (2)

Mirza715
Mirza715

Reputation: 420

I was also having same issue as yours. If you are using Generic views then do this:

Views:

def perform_create(self, serializer):
    serializer.save(user=self.request.user)

Serializer:

You just have to add this in you serializer in order to save the user. PrimaryKeyRelatedField is used to represent the target of the relationship using its primary key. read_only=True to make this field read only.

class WaitercallCreateSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True)
    class Meta:
        model = Waitercall
        fields = ('order', 'user', 'done', 'type_of_call')

Upvotes: 2

arjunattam
arjunattam

Reputation: 2819

The error is coming from the serializer validation, which is called before the create method is called. Therefore, the changes to the create method are not making a difference. You can fix this by calling out that the user field is not required in the serializer. This will look like:

from rest_framework import serializers

class WaitercallCreateSerializer(serializers.ModelSerializer):
    user = serializers.JSONField(required=False)

    class Meta:
        model = Waitercall
        fields = ('order', 'user', 'done', 'type_of_call')
        read_only_fields = ('user', 'done')

Upvotes: 4

Related Questions