求助:Django模板中如何判断帖子是否已被当前用户点赞
Django判断用户是否点赞帖子并切换箭头状态
需求说明
通过Post和Upvoted数据表,实现:判断当前登录用户是否点赞某篇帖子,若已点赞则显示实心箭头,未点赞则显示空心箭头。目前已尝试将Upvoted模型传递至模板,但模板判断代码无效,需修正实现方式。
现有代码
模型代码
class Post(models.Model): user = models.ForeignKey(User, related_name="posts", on_delete=models.DO_NOTHING) body = models.CharField(max_length=255) image = models.ImageField( default="onebyone.png", upload_to="images/", blank=True, null=True ) created_at = models.DateTimeField(auto_now_add=True) post_karma = models.IntegerField(default=0, blank=True, null=True) comment_count = models.IntegerField(default=0, blank=True, null=True) def __str__(self): return f"{self.user.username} - {self.created_at.strftime('%Y-%m-%d')} - {self.body[:30]}" class Upvoted(models.Model): user = models.ForeignKey(User, related_name="upvoted", on_delete=models.CASCADE) post = models.ForeignKey(Post, related_name="upvoted", on_delete=models.CASCADE) upvoted_at = models.DateTimeField(auto_now_add=True) def __str__(self): return ( f"{self.user.username} - {self.post.user.username} - {self.post.body[:30]}")
视图代码
@login_required def dashboard(request): form = PostForm(request.POST, request.FILES) if form.is_valid(): img = form.cleaned_data["image"] body = form.cleaned_data["body"] if img is None: img = "images/onebyone.png" post = Post.objects.create(user=request.user, image=img, body=body) post.save() return redirect("posty:dashboard") sorting = request.GET.get("sort") ordering = { "date_sort": "-created_at", "karma_sort": "-post_karma", "comment_sort": "-comment_count", None: "-created_at", } followed_posts = Post.objects.filter( user__profile__in=request.user.profile.follows.all() ).order_by(ordering[sorting]) now = datetime.now() return render( request, "posty/dashboard.html", {"form": form, "posts": followed_posts, "comment": Comment, "now": now, "upvote" : Upvoted, "downvote" : Downvoted},)
无效的模板判断代码
{% if post.id in upvote.post_id.all %}
正确实现方法
1. 优化视图:传递当前用户的点赞帖子ID列表
原视图传递的是Upvoted模型类,无法直接用于模板判断。需先获取当前用户所有点赞的帖子ID,作为列表传递至模板,同时移除无用的模型类传递:
修改视图中的代码,在return render前添加:
# 获取当前用户点赞的所有帖子ID,生成列表 upvoted_post_ids = request.user.upvoted.values_list('post_id', flat=True)
然后更新render的context参数,替换掉原来的"upvote" : Upvoted,添加"upvoted_post_ids": upvoted_post_ids:
return render( request, "posty/dashboard.html", {"form": form, "posts": followed_posts, "comment": Comment, "now": now, "upvoted_post_ids": upvoted_post_ids, "downvote" : Downvoted},)
2. 模板中实现判断与箭头切换
在遍历帖子的循环中,通过判断当前帖子ID是否在upvoted_post_ids列表内,渲染不同状态的箭头:
{% for post in posts %} <!-- 其他帖子内容渲染 --> <div class="vote-area"> {% if post.id in upvoted_post_ids %} <!-- 已点赞:显示实心箭头,可替换为图标类或自定义样式 --> <span class="solid-up-arrow">↑</span> {% else %} <!-- 未点赞:显示空心箭头 --> <span class="hollow-up-arrow">↑</span> {% endif %} <span>{{ post.post_karma }}</span> </div> {% endfor %}
可选优化:减少数据库查询(进阶)
如果担心性能问题,可以用prefetch_related提前加载帖子的点赞记录,避免模板中产生N+1查询:
修改视图中获取followed_posts的代码:
followed_posts = Post.objects.filter( user__profile__in=request.user.profile.follows.all() ).order_by(ordering[sorting]).prefetch_related('upvoted')
此时模板判断可以改为:
{% if post.upvoted.filter(user=request.user).exists %} <span class="solid-up-arrow">↑</span> {% else %} <span class="hollow-up-arrow">↑</span> {% endif %}
这种方法无需传递ID列表,但每次判断会执行一次数据库过滤,对于帖子数量较多的场景,推荐第一种传递ID列表的方式,性能更优。
内容的提问来源于stack exchange,提问作者Aaron sc
相关产品推荐
相关产品推荐

