You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:50:22