9

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?

Leah Sapan
  • 3,621
  • 7
  • 33
  • 57

3 Answers3

34

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.

Saneem
  • 866
  • 9
  • 10
7

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.

Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
2

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)
Cemal
  • 73
  • 7
  • Thanks for your solution. But I feel that this logic should be placed in the serialiser or model. – Beast May 10 '23 at 07:59