Django REST Framework: Как использовать префетчированные наборы запросов в дочерних сериализаторах во вложенных сериализаторах

Я хочу вызвать queryset, предварительно извлеченный из View, из вложенного дочернего сериализатора. Я попробовал сделать следующее, но это не сработало так, как я задумал. Как я могу вызвать предварительно выбранный кверисет из дочернего сериализатора?

#views.py
class PlaylistListView(generics.ListAPIView):
    serializer_class = PlaylistSerializer

    def get_queryset(self):
        return (
            Playlist.objects.all()
            .prefetch_related("user", "user__emailaddress_set")
        )

#serializers.py
class UserDetailSerializer(serializers.ModelSerializer):
    is_verified = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ("is_verified",)

    def get_is_verified(self, user):
        return user.emailaddress_set.filter(verified=1).count() > 0


class PlaylistSerializer(serializers.ModelSerializer):
    user = UserDetailSerializer(read_only=True)

    class Meta:
        model = Playlist
        fields = ("user",)

Мы можем использовать объект Prefetch для предварительной выборки пользователей с аннотацией о том, проверен он или нет, verified, похоже, является булевой функцией, поэтому выбор Max даст нам True, если все связанные электронные письма проверены. В сериализаторе мы можем искать эту аннотацию и, если она существует, возвращать ее, иначе возвращается то же самое, что и раньше

from django.db.models import Prefetch, Max


class PlaylistListView(generics.ListAPIView):
    serializer_class = PlaylistSerializer

    def get_queryset(self):
        return Playlist.objects.prefetch_related(
            Prefetch('user', queryset=User.objects.annotate(_is_verified=Max('emailaddress__verified')))
        )


class UserDetailSerializer(serializers.ModelSerializer):
    is_verified = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ("is_verified",)

    def get_is_verified(self, user):
        if hasattr(user, "_is_verified"):
            return user._is_verified
        else:
            return user.emailaddress_set.filter(verified=True).exists()
Вернуться на верх