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

如何将关联模型结果纳入QuerySet?循环渲染帖子时展示点赞者

解决Django关联模型查询与模板渲染点赞者的问题

嘿,我来帮你搞定这个问题!首先得先修正模型设计的小问题,这是后续查询和渲染的基础,然后一步步实现你的需求。

第一步:修正PostLike模型的关联逻辑

你现在用IntegerField存储post ID的方式不符合Django ORM的关联规范,不仅查询麻烦还容易出错,而且要显示点赞者,PostLike必须关联User模型。咱们把模型改成这样:

from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    title = models.CharField(max_length=75, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    creator = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
    body = models.TextField(max_length=10000)
    published = models.BooleanField(default=True)

class PostLike(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes')  # 用ForeignKey关联Post,自定义关联名更直观
    user = models.ForeignKey(User, on_delete=models.CASCADE)  # 新增用户关联字段,记录点赞者
    created = models.DateTimeField(auto_now_add=True)  # 可选:记录点赞时间

    class Meta:
        unique_together = ('post', 'user')  # 约束:同一用户不能给同一篇帖子重复点赞

这里的关键调整:

  • 把PostLike.post改成ForeignKey关联Post,并设置related_name='likes',后续查询帖子的点赞记录时,用post.likes比默认的postlike_set更易读
  • 新增user字段关联User,这是记录点赞者的核心
  • 加unique_together约束,避免重复点赞的无效数据

第二步:优化QuerySet,预取关联数据

如果直接在模板里遍历每个帖子的点赞记录,会触发N+1查询(先查所有帖子,再逐个查点赞),性能很差。咱们用prefetch_related一次性预取所有关联的点赞记录,同时用select_related预取点赞者的用户信息:

类视图写法

from django.views.generic import ListView
from .models import Post
from django.db.models import Prefetch

class PostListView(ListView):
    model = Post
    template_name = 'posts/post_list.html'
    context_object_name = 'posts'

    def get_queryset(self):
        # 预取每个帖子的点赞记录,同时预取点赞者的用户数据
        return Post.objects.filter(published=True).prefetch_related(
            Prefetch('likes', queryset=PostLike.objects.select_related('user'))
        )

函数视图写法

from django.shortcuts import render
from .models import Post
from django.db.models import Prefetch

def post_list(request):
    posts = Post.objects.filter(published=True).prefetch_related(
        Prefetch('likes', queryset=PostLike.objects.select_related('user'))
    )
    return render(request, 'posts/post_list.html', {'posts': posts})

第三步:模板中渲染每个帖子的点赞者

现在在模板里可以轻松遍历每个帖子的点赞者了,而且不会触发额外的数据库查询:

{% for post in posts %}
    <div class="post-card">
        <h3>{{ post.title }}</h3>
        <p class="post-meta">
            作者: {{ post.creator.username }} | 发布时间: {{ post.created|date:"Y-m-d H:i" }}
        </p>
        <div class="post-body">{{ post.body|truncatechars:200 }}</div>
        
        <!-- 点赞者展示区域 -->
        <div class="post-likes">
            <h4>点赞者 ({{ post.likes.count }})</h4>
            {% if post.likes.exists %}
                <ul class="like-users">
                    {% for like in post.likes %}
                        <li>{{ like.user.username }}</li>
                    {% endfor %}
                </ul>
            {% else %}
                <p>还没有小伙伴点赞哦 😊</p>
            {% endif %}
        </div>
    </div>
{% endfor %}

这里用post.likes(咱们自定义的related_name)直接访问帖子的所有点赞记录,like.user直接获取点赞者的用户信息,因为已经预取过数据,性能拉满。

内容的提问来源于stack exchange,提问作者Babr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:28:49