Как передать контекст от одного сериализатора к другому в 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, и я не знал, что это можно обойти, просто создав пользовательский метод.

Вернуться на верх