1๐
I can think of a two ways to achieve this.
-
If you just need a
boolean
True
/False
whether thePost
is liked by therequest.user
, you can use.extra
.1.1. Alter your
BlogPost
Queryset
to something like this:class BlogPostQuerySet(models.QuerySet): def annotate_is_liked_by_user(self, user): return self.extra( select = {'is_liked': 'EXISTS( \ SELECT `id` FROM `blogpostlikes` \ WHERE `blogpostlikes`.`blogpost_id` = `blogpost`.id \ AND `blogpostlikes`.`user_id` = %s)' % user.id } ) class BlogPost # other stuffs here objects = BlogPostQuerySet.as_manager()
1.2. Alter
get_queryset
method insideBlogPostList
viewclass BlogPostList(ListAPIView): def get_queryset(self): user = self.request.user return BlogPost.objects.annotate_is_liked_by_user(user)
1.3. Add the new field to the
BlogPostSerializer
class BlogPostSerializer(serializer.ModelSerializer): # .... is_liked = serializers.BooleanField(source='is_liked') # ...
-
Get the whole
BlogPostLike
object.2.1.Alter the
get_queryset
method.class BlogPostList(ListAPIView): def get_queryset(self): user = self.request.user return BlogPost.objects.prefetch_related( Prefetch( 'likes', queryset=BlogPostLikes.objects.filter(user=user) \ .select_related('user'), to_attr='likes_by_request_user' ) )
2.2. Alter the
serializer
. But this can be done in two ways:2.2.1. Serializing a list with one item inside:
class BlogPostSerializer(serializer.ModelSerializer): # ... likes_by_request_user = BlogPostLikesSerializer(many=True)
and remove the
blogpost = BlogPostSerializer()
fromBlogPostLikesSerializer
. I think this can lead to infinite loop.2.2.2 Serialize a single object:
class BlogPostSerializer(serializer.ModelSerializer): # ... like_by_request_user = BlogPostLikesSerializer(source='get_last_like', required=False)
but this way you will have to add a new method inside your
BlogPost
object to return this singleLike
objectclass BlogPost(models.Model): #... def get_last_like(self): if hasattr(self, 'likes_by_request_user') and len(self.likes_by_request_user) > 0: return self.likes_by_request_user[0] return None
0๐
You can use a SerializerMethodField to get your flag dynamically, like this:
class BlogPostSerializer(serializer.ModelSerializer):
user = SomeUserSerializer()
likes = BlogPostLikesSerializer()
has_liked = SerializerMethodField("get_has_liked")
class Meta:
model = BlogPostLikes
fields = ("id", "user", "likes", "content", "image", "has_liked")
def get_has_liked(self, obj):
user = self.context.get('request').user
return len([l.user.id == user.id for l in obj.likes]) > 0
However, youโd need to pass the request when instantiating your serializer, by doing something like this: serializer = BlogPostSerializer(context={'request': request})
- [Answer]-Location of rendered html files for django
- [Answer]-The page is not going through after all, I feel I did everything right. Can someone spot my mistake
- [Answer]-Filter/limit django order_by
- [Answer]-Optimized query to match and exclude multiple ManyToMany entries