Django Serializer中如何通过反向外键实现判断用户是否点赞的liked字段
实现步骤
1. 调整序列化器逻辑
你需要通过SerializerMethodField定义动态计算的liked字段,同时从序列化器上下文获取当前请求的用户做判断:
from rest_framework import serializers from .models import Post, PostLike class PostSerializer(serializers.ModelSerializer): # 声明为动态计算的只读布尔字段 liked = serializers.SerializerMethodField() class Meta: model = Post fields = ("content","image","timestamp","liked") def get_liked(self, obj): # 从上下文取出当前请求的登录用户 current_user = self.context["request"].user # 校验该用户是否对当前帖子有点赞记录 return PostLike.objects.filter(user=current_user, post=obj).exists()
2. 修改视图传递上下文
序列化器默认拿不到请求对象,你需要在实例化序列化器时手动传入包含request的上下文,同时修正原代码里的笔误:
from django.http import JsonResponse from django.contrib.auth.decorators import login_required from .models import Post from .serializers import PostSerializer @login_required() def AllPosts(request): # 原代码笔误:模型名为Post不是Posts obj = Post.objects.all() # 传入request到序列化器上下文 serializer = PostSerializer(obj, many=True, context={"request": request}) return JsonResponse(serializer.data, safe=False)
性能优化(生产环境推荐)
上面的基础实现会产生N+1查询问题,返回帖子数量较多时性能很差,可以通过数据库注解提前计算点赞状态,全局只查2次数据库:
优化后的视图代码
@login_required() def AllPosts(request): from django.db.models import Exists, OuterRef # 构造点赞子查询 like_subquery = PostLike.objects.filter(user=request.user, post=OuterRef("pk")) # 提前把点赞状态注解到每个Post对象上 obj = Post.objects.annotate(is_liked=Exists(like_subquery)).all() serializer = PostSerializer(obj, many=True, context={"request": request}) return JsonResponse(serializer.data, safe=False)
优化后的序列化器判断逻辑
def get_liked(self, obj): # 直接返回提前注解的字段,不需要重复查库 return obj.is_liked
补充原代码笔误提醒
PostLike模型里的外键拼写错误:models.ForiegnKey需改为models.ForeignKey- 视图里的模型名拼写错误:
Posts.objects.all()需改为Post.objects.all()
内容的提问来源于stack exchange,提问作者RoyalBosS
相关产品推荐
相关产品推荐

