Leah Sapan
Leah Sapan

Reputation: 3791

Modify data before validation step with django rest framework

I have a simple Model that stores the user that created it with a ForeignKey. The model has a corresponding ModelSerializer and ModelViewSet.

The problem is that when the user submits a POST to create a new record, the user should be set by the backend. I tried overriding perform_create on the ModelViewSet to set the user, but it actually still fails during the validation step (which makes sense). It comes back saying the user field is required.

I'm thinking about overriding the user field on the ModelSerializer to be optional, but I feel like there's probably a cleaner and more efficient way to do this. Any ideas?

Upvotes: 12

Views: 12358

Answers (3)

Cemal
Cemal

Reputation: 93

Old topic but it could be useful for someone.

If you want to alter your data before validation of serializer:

serializer.initial_data["your_key"] = "your data"
serializer.is_valid(raise_exception=True)

Upvotes: 2

Saneem
Saneem

Reputation: 926

I came across this answer while looking for a way to update values before the control goes to the validator.

This might be useful for someone else - here's how I finally did it (DRF 3) without rewriting the whole validator.

class MyModelSerializer(serializers.ModelSerializer):
    def to_internal_value(self, data):
        data['user'] = '<Set Value Here>'

        return super(MyModelSerializer, self).to_internal_value(data)

For those who're curious, I used this to round decimal values to precision defined in the model so that the validator doesn't throw errors.

Upvotes: 40

Rahul Gupta
Rahul Gupta

Reputation: 47856

You can make the user field as read_only.

This will ensure that the field is used when serializing a representation, but is not used when creating or updating an instance during deserialization.

In your serializers, you can do something like:

class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        extra_kwargs = {
            'user' : {'read_only' : True} # define the 'user' field as 'read-only'
        }

You can then override the perform_create() and set the user as per your requirements.

Upvotes: 7

Related Questions