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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:35:23