Django REST Framework:如何在嵌套序列化程序的子序列化程序中使用预取查询集

Django REST Framework: How to use prefetched queriesets in child serializers in nested serializers

我想调用从嵌套序列化程序子视图中预取的查询集。 我尝试了以下但它没有按我预期的方式工作。 如何从子序列化程序调用预取查询集?

#models.py
class User(AbstractBaseUser, PermissionsMixin):
   ...

#This is allauth.models
class EmailAddress(models.Model):
    user = models.ForeignKey(
        allauth_app_settings.USER_MODEL,
        verbose_name=_("user"),
        on_delete=models.CASCADE,
    )
    verified = models.BooleanField(verbose_name=_("verified"), default=False)
#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 # <- here


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

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

function max(boolean) does not exist: error image

我们可以使用 Prefetch 对象来预取带有注释的用户,以判断是否已验证,verified 似乎是一个布尔值,因此选择 Max 将给出我们 True 如果任何相关电子邮件已验证。然后在序列化程序中我们可以查找此注释,如果它存在 return 否则 return 与之前相同

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()