Reputation: 6980
I have a problem where a read-only attribute is not behaving as expected. I have looked at this question and other sources to try and solve the issue but to no avail.
The endpoint is for saving and listing user favorites. Users can favourite multiple object types so I use the content types framework.
# serializers.py
class FavouriteSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
type = serializers.CharField(source='content_type', read_only=True)
object = FavouriteObjectRelatedField(read_only=True)
content_type = serializers.CharField(write_only=True)
object_id = serializers.IntegerField(write_only=True)
def create(self, validated_data, *args, **kwargs):
content_object = Favourites.objects.get_content_object(validated_data.get('object_id'),
validated_data.get('content_type'))
user = kwargs.get('user')
return Favourites.objects.create_favourite(content_object, user)
class Meta:
model = Favourites
fields = ('type', 'object','user','content_type','object_id')
This is the FavouriteObjectRelatedField
serializer that is required to dynamically serialize an object based on its type.
# serializers.py
class FavouriteObjectRelatedField(serializers.RelatedField):
"""
A custom serializer to use for favourited objects.
"""
def to_representation(self, value):
"""
Serialize favourited objects using their respective serializer
"""
if isinstance(value, Track):
track = TrackBuilder(value).get_info()
serializer = TrackSerializer(track, context=self.context, read_only=True)
elif isinstance(value, News):
serializer = NewsSerializer(value, context=self.context, read_only=True)
else:
raise Exception("Unexpected type of favourited object")
return serializer.data
And the view. I override the perform_create
method so to add the user instance which is retrieved from a url parameter.
#views.py
class UserFavouritesList(generics.ListCreateAPIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)
serializer_class = FavouriteSerializer
def get_user(self):
user_id = self.kwargs.get('user_id')
try:
return get_user_model().objects.get(pk=user_id)
except get_user_model().DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
def perform_create(self, serializer):
serializer.save(user=self.get_user())
def get_queryset(self):
return Favourites.objects.user_favourites(self.get_user())
I always get a user field required error. However, if I removed the user
field this error is obviously gone. Interestingly, if I rename the user
field to owner
I still get the same error with the field name specified as user
. Error here:
{
"user": [
"This field is required."
]
}
As with one of the answers, I have already tried setting required=True
but it has no effect.
Removing read_only=True
is not an option since the user instance shouldn't be editable from this endpoint.
Another interesting development: if I remove the type
field it works as expected. Strange but somehow accessing the content_type
field must have an effect on validation.
Upvotes: 3
Views: 4234
Reputation: 213223
Try setting required=False
in there, instead of read_only=True
.
user = UserSerializer(required=False)
Upvotes: 1