我构建了一些Blog API,但遇到了问题。
在序列化器中,有一个方法字段可返回用户是否喜欢该帖子的请求。问题在于,该字段每次返回帖子都会命中用户数据库,这意味着如果返回1000个帖子,则用户数据库将被命中1000次。 如何避免这种情况?第一个想法是将请求用户分配给全局变量之类的东西,但是我不知道该怎么做。
这是序列化器
class DashboardSerializer(serializers.ModelSerializer):
image = serializers.ImageField(allow_null=True, use_url=True)
likes_count = serializers.SerializerMethodField(read_only=True)
tags = TagSerializer(many=True, read_only=True)
user_has_liked = serializers.SerializerMethodField(read_only=True)
owner = UserField(read_only=True)
comments = CommentsField(read_only=True, many=True, source='two_latest_comments')
comments_count = serializers.SerializerMethodField()
class Meta:
model = Blog
fields = ['id', 'title', 'owner', 'likes_count', 'user_has_liked',
'image', 'video', 'tags', 'get_elapsed_time_after_created',
'comments', 'comments_count']
ordering = ['created_at']
def get_likes_count(self, instance):
return instance.likes.count()
def get_user_has_liked(self, instance):
request = self.context.get('request')
***return instance.likes.filter(pk=request.user.pk).exists()***
*******request.user.pk hits the DB.*********
def get_comments_count(self, instance):
return instance.comments.count()
谢谢。
答案 0 :(得分:1)
在要传递给序列化程序的查询集上使用.annotate
和Exists
subqyery,然后调整字段:
序列化器调用:
queryset = ... # your queryset
user_commented = Comment.objects.filter(
blog_id=OuterRef("pk"),
user_id=request.user.pk,
)
data = DashboardSerializer(instance=queryset.annotate(
likes_count=Count("likes"),
comments_count=Count("comments"),
user_has_liked=Exists(user_commented),
)
序列化器:
class DashboardSerializer(serializers.ModelSerializer):
image = serializers.ImageField(allow_null=True, use_url=True)
likes_count = serializers.IntegerField(read_only=True)
tags = TagSerializer(many=True, read_only=True)
user_has_liked = serializers.BooleanField(read_only=True)
owner = UserField(read_only=True)
comments = CommentsField(read_only=True, many=True, source='two_latest_comments')
comments_count = serializers.IntegerField(read_only=True)
class Meta:
model = Blog
fields = ['id', 'title', 'owner', 'likes_count', 'user_has_liked',
'image', 'video', 'tags', 'get_elapsed_time_after_created',
'comments', 'comments_count']
ordering = ['created_at']