Как передать контекст от одного сериализатора к другому в DRF [2024]?
Я видел много дублирующих тем по этому вопросу, в частности, вот эту context in nested serializers django rest framework, но ни одна из них не сработала для меня. Я перепробовал большинство решений, которые встречаются в каждой теме, в частности CustomSerializers, использование родительского init() и использование родительского to_representation(), но контекст никогда не передается от родителя к ребенку. По-видимому, в новых версиях django он должен передаваться автоматически, но у меня этого не происходит. (Django 5.0.2)
В моем примере я сериализую пост, комментарии которого сериализуются вызовом сериализатора комментариев. Для каждого сериализуемого комментария я хочу проверить, проголосовал ли пользователь за него, создав поле user_vote. Когда я печатаю запрос от родителя, он печатается нормально, однако от дочерней версии запрос пуст.
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__'
В конце концов я самостоятельно нашел решение. По всей видимости, Django в какой-то момент автоматически передавал контекст дочерним сериализаторам, но начиная с версии 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
Решением является установка поля в родительском сериализаторе, а затем использование пользовательской функции для установки его значения в дочернем сериализаторе при передаче контекста. Причина моих проблем заключалась в том, что контекст был недоступен внутри класса родительского сериализатора, поскольку внутри определений классов нет self, и я не знал, что это можно обойти, просто создав пользовательский метод.