How can I pass context from one serializer to another in DRF [2024]?
I have seen many duplicate threads on this, most notably this context in nested serializers django rest framework, but none have worked for me. I have tried most solutions I see in every thread most notably CustomSerializers, using parents init(), and using parents to_representation(), but the context never passes from parent to child. Apparently it is supposed to pass automatically as of the newer django versions but it doesnt for me. (Django 5.0.2)
In my example I serialize a post which's comments are serialized by calling the comment serializer. For every comment being serialized, I want to check if the user has voted on it yet by creating a field user_vote. When I print the request from the parent it prints normally, however from the child it request is empty.
Serializers.py
class CommentSerializer(ModelSerializer):
child_comment = serializers.SerializerMethodField()
user_vote = serializers.SerializerMethodField()
class Meta:
model = Comment
fields = '__all__'
def get_user_vote(self, obj):
# Get the current user from the request
print(self.context, file=sys.stderr)
user = self.context['request'].user
# Check if a vote exists for the current user and comment
try:
vote = Vote.objects.get(user=user, comment=obj)
return vote.value
except Vote.DoesNotExist:
return 0
class PostSerializerSingle(ModelSerializer):
images = SheetMusicImageSerializer(many=True)
comments = CommentSerializer(many=True)
class Meta:
model = Post
fields = '__all__'
In the end I came up with a solution by myself. Apparently Django at some point automatically passed the context to children serializers but that is no longer the case as of Django 5.0.2.
code:
class CommentSerializer(ModelSerializer):
child_comment = serializers.SerializerMethodField()
class Meta:
model = Comment
fields = '__all__'
# example function
def get_child_comment(self, obj):
# you can access the context in the child function now
print(self.context.get('request'))
return serializer.data
class PostSerializerSingle(ModelSerializer):
user_vote = serializers.SerializerMethodField()
images = SheetMusicImageSerializer(many=True)
comments = serializers.SerializerMethodField()
class Meta:
model = Post
fields = '__all__'
# pass in the context through here
def get_comments(self, obj):
comments = obj.comments.all()
serializer = CommentSerializer(comments, many=True, context={'request': self.context.get('request') })
return serializer.data
The solution is just by setting a field in the parent serializer, then using a custom function to set its value to the child serializer while passing the context in. The reason I had trouble was that the context wasnt accessible inside of the parent serializer class as there is no self inside of class definitions, and I didnt realize this could be circumvented through simply making a custom method.