如何将关联模型结果纳入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
相关产品推荐
相关产品推荐

