I am trying to create a queryset that returns Boolean from a queryset prefetched with a reverse reference by SerializerMethodField
, as shown in the code below.
I'm creating one that determines if there is an object for the current user and returns Boolean.
However, when I use the prefetched queryset to filter by the current user as shown below, a new queryset is issued instead of the prefetched queryset, and the n 1 problem occurs.
In the following code, how can we save the queryset and return Booelan?
class VideoSerializer(serializers.ModelSerializer):
is_viewed = serializers.SerializerMethodField()
is_favorited = serializers.SerializerMethodField()
is_wl = serializers.SerializerMethodField()
class Meta:
model = Video
fields = (
"pk",
"is_viewed",
"is_favorited",
"is_wl",
)
@staticmethod
def setup_eager_loading(queryset):
queryset.prefetch_related('history_set', 'favorite_set')
def get_is_viewed(self, obj):
user = self.context["request"].user
if user.is_authenticated:
try:
obj.history_set.get(user=user) # <- here
return True
except History.DoesNotExist:
pass
return False
def get_is_favorited(self, obj):
user = self.context["request"].user
if user.is_authenticated:
try:
obj.favorite_set.get(user=user) # <- here
return True
except Favorite.DoesNotExist:
pass
return False
def get_is_wl(self, obj):
user = self.context["request"].user
if user.is_authenticated:
try:
Track.objects.get(playlist__user=user, playlist__is_wl=True, video=obj)
return True
except Track.DoesNotExist:
pass
return False
https://docs.djangoproject.com/en/3.2/ref/models/querysets/
I think using subquery and Exists query expression is better option, as 'Utkucan Bıyıklı' suggested.
CodePudding user response:
By reverse reference, i understand you are referring a foreignkey field, in that case you need to use select_related
, prefetch_related
is used for many-many fields.
Based on it you can use any of the below code. make sure to return the queryset.
@staticmethod
def setup_eager_loading(queryset):
#prefetch_related for 'to-many' relationships
queryset.prefetch_related('history_set', 'favorite_set')
return quesyset
@staticmethod
def setup_eager_loading(queryset):
#select_related for 'foreign key' relationships
queryset = queryset.select_related('history_set', 'favorite_set')
return queryset