Instance for nested serializer is not viewable
Using Django Rest Framework 3.1 I am doing the following:
# models.py
class OrganizationUser(models.Model):
user = models.ForeignKey(USER_MODEL)
organization = models.ForeignKey(ORGANIZATION_MODEL)
# serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
class OrganizationUserSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = OrganizationUser
I've simplified some of the above code to isolate the problem.
The problem I'm running into is that when I try to update the OrganizationUser via the viewet, I get a validation error:
{"user":{"username":["This field must be unique."]}}
In debugging, I found that the error was caused by UniqueValidator and because the custom instance is not set in the parent username field (i.e. UserSerializer).
So, I added the following implementation to_internal_value to OrganizationUserSerializer and then it worked correctly:
def to_internal_value(self, data):
if self.instance:
# set user instance on its serializer
user = self.instance.user
self.fields['user'].instance = user
# make sure correct user is specified in request data
try:
user_id = self.initial_data['user']['id']
except KeyError:
raise fw_serializers.ValidationError('User must be specified')
if user_id != user.id:
raise fw_serializers.ValidationError('Invalid user specified')
return super(OrganizationUserSerializer, self).to_internal_value(data)
But I thought the REST Framework would do it automatically? Isn't that so? Is the application responsible for finding any nested serializer instances?
source to share
You can implement this behavior by changing the UserSerializer to_internal_value method:
def to_internal_value(self, data):
if data and data.get('username'):
return self.Meta.model.objects.get(username=data['username'])
return super().to_internal_value(data)
So now, if you are sending some data to a UserSerializer that has the username as part of the data, it is assumed that you are sending data belonging to an existing object, view it, and return it.
source to share