I want to call a queryset prefetched from a View from a nested serializer child. I tried the following but it did not work the way I intended. How can I call a prefetched queryset from a child serializer?
#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
CodePudding user response:
We can use a Prefetch
object to prefetch the users with an annotation for if it is verified or not, verified
seems to be a boolean so selecting the Max
will give us True
if any related emails are verified. In the serializer we can then look for this annotation and if it exists return it otherwise return the same thing as before
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()