Django模型查询求助:分类页展示每个分类的单篇文章
解决方案:分类页面展示分类+关联文章
1. 先确认模型关联正确性
确保Post和Category的外键关联配置正确,尤其是反向关联的命名:
# models.py from django.db import models class Category(models.Model): name = models.CharField(max_length=100) # 其他自定义字段(如描述、slug等) class Post(models.Model): title = models.CharField(max_length=200) excerpt = models.TextField(blank=True) pub_date = models.DateTimeField(auto_now_add=True) # 外键关联到Category,指定related_name方便反向查询 category = models.ForeignKey( Category, on_delete=models.CASCADE, related_name='posts' # 关键:这个名字要和后面视图/模板里的调用一致 )
2. 视图层优化查询并传递数据
用预取查询避免N+1性能问题,同时直接获取每个分类的第一篇文章(以最新发布为例):
# views.py(类视图写法) from django.views.generic import ListView from django.db import models from .models import Category, Post class CategoryListView(ListView): model = Category template_name = "categories/category_list.html" context_object_name = "categories" # 模板中要用到的变量名 def get_queryset(self): # 预取每个分类的最新1篇文章,存到latest_post属性 return Category.objects.prefetch_related( models.Prefetch( "posts", queryset=Post.objects.order_by("-pub_date")[:1], to_attr="latest_post" ) ) # 函数视图写法(可选) # def category_list(request): # categories = Category.objects.prefetch_related( # models.Prefetch( # "posts", # queryset=Post.objects.order_by("-pub_date")[:1], # to_attr="latest_post" # ) # ).all() # return render(request, "categories/category_list.html", {"categories": categories})
3. 模板层正确循环渲染
模板中循环分类,同时判断是否存在关联文章,避免报错:
<!-- categories/category_list.html --> <div class="category-container"> {% for category in categories %} <div class="category-card"> <h2>{{ category.name }}</h2> {% if category.latest_post %} <!-- latest_post是列表,取第一个元素 --> <div class="post-card"> <h3>{{ category.latest_post.0.title }}</h3> <p>{{ category.latest_post.0.excerpt|truncatewords:25 }}</p> </div> {% else %} <p>该分类暂无文章</p> {% endif %} </div> {% empty %} <p>暂无分类数据</p> {% endfor %} </div>
4. 排查无输出的常见原因
- 空数据问题:检查数据库中是否存在
Category记录,以及对应分类下是否有Post关联 - 变量名不匹配:确保视图传递的上下文变量名(如
categories)和模板中循环的变量名完全一致 - 反向关联名错误:如果模型中没指定
related_name,反向关联默认是post_set,模板/视图中要改成category.post_set.first - 模板继承问题:确认循环代码放在了母版的
{% block %}块内,没有被母版内容覆盖
内容的提问来源于stack exchange,提问作者Israel Akinoso
相关产品推荐
相关产品推荐

