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

Django模板中IF嵌套For循环无法正确展示对应分类文章

问题描述

在分类栏目中通过内嵌For循环的IF条件,尝试实现仅展示对应分类下文章的效果,但当前页面会渲染所有已发布文章,无法过滤出仅归属目标分类的内容。

相关代码与截图

  • home.html 页面截图:
    home.html运行截图
  • 原有home.html代码:
{% if articles.category == Sports %}
    {% for article in articles %}
    <div class="position-relative">
        <img class="img-fluid w-100" src="{{article.cover.url}}" style="object-fit: cover;">
        <div class="overlay position-relative bg-light">
            <div class="mb-2" style="font-size: 13px;">
                <a href="">{{article.title}}</a>
                <span class="px-1">/</span>
                <span>{{article.created_at}}</span>
            </div>
            <a class="h4 m-0" href="">{{article.description}}</a>
        </div>
    </div>
    {% endfor %}
{% endif %}
  • 原有views.py代码:
def home (request):   
    cats = Category.objects.all()
    articles = Article.objects.filter( is_published=True).order_by('-category')
    
    return render (request,'pages/home.html',
    context={
    'cats': cats, 
    'articles': articles
    })
问题根源

现有代码存在两个核心错误,导致过滤逻辑完全失效:

  1. 判断位置错误:{% if %}写在了{% for %}循环外层,articles是所有文章的查询集对象,本身不存在单篇文章才有的category属性,外层判断根本不会按预期生效
  2. 判断语法错误:Sports没有加引号,Django模板会将其识别为未定义变量而非字符串;就算判断位置正确,直接拿整个文章查询集做分类匹配,也不会对单篇文章生效
修复方案

方案1:后端预处理分组(推荐,性能更优)

先在后端把文章按分类归类,减少模板层的重复判断,适合文章量大的场景。

  1. 修改views.py:
def home(request):   
    cats = Category.objects.all()
    published_articles = Article.objects.filter(is_published=True)
    # 按分类组装对应文章列表
    category_articles = {}
    for cat in cats:
        category_articles[cat.name] = published_articles.filter(category=cat)
    
    return render(request, 'pages/home.html', context={
        'cats': cats, 
        'category_articles': category_articles
    })
  1. 新增字典取值自定义模板过滤器(Django模板默认不支持直接用变量取字典键):
    在对应app下新建templatetags文件夹,创建dict_filter.py文件:
from django import template
register = template.Library()

@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)
  1. 修改home.html:
{% load dict_filter %}
{% for cat in cats %}
{# 以体育分类为例,其他分类替换对应判断值即可 #}
{% if cat.name == "Sports" %}
<section>
    <h3>{{ cat.name }}</h3>
    {% for article in category_articles|get_item:cat.name %}
    <div class="position-relative">
        <img class="img-fluid w-100" src="{{article.cover.url}}" style="object-fit: cover;">
        <div class="overlay position-relative bg-light">
            <div class="mb-2" style="font-size: 13px;">
                <a href="">{{article.title}}</a>
                <span class="px-1">/</span>
                <span>{{article.created_at}}</span>
            </div>
            <a class="h4 m-0" href="">{{article.description}}</a>
        </div>
    </div>
    {% endfor %}
</section>
{% endif %}
{% endfor %}

方案2:模板层直接判断(无需新增过滤器,适合小数据量场景)

不用修改原有views.py,直接调整模板判断逻辑位置,在循环内逐篇校验文章分类即可:

<section>
    <h3>体育分类</h3>
    {% for article in articles %}
    {# 注意字符串值必须加引号,外键关联要取分类的name字段匹配 #}
    {% if article.category.name == "Sports" %}
    <div class="position-relative">
        <img class="img-fluid w-100" src="{{article.cover.url}}" style="object-fit: cover;">
        <div class="overlay position-relative bg-light">
            <div class="mb-2" style="font-size: 13px;">
                <a href="">{{article.title}}</a>
                <span class="px-1">/</span>
                <span>{{article.created_at}}</span>
            </div>
            <a class="h4 m-0" href="">{{article.description}}</a>
        </div>
    </div>
    {% endif %}
    {% endfor %}
</section>
注意事项
  • 字符串匹配必须加引号:模板中做字符串相等判断时,匹配值必须加双引号,否则会被识别为变量导致判断失效
  • 判断位置不能放错:分类判断必须放在文章循环内部,逐篇校验单篇文章的分类属性,不能在循环外层对整个文章查询集做判断
  • 外键匹配要取具体字段:如果分类是外键关联,必须取分类的具体字段(比如category.name)做匹配,不能直接拿外键对象和字符串对比

内容的提问来源于stack exchange,提问作者CARLOS EDUARDO VIEIRA MARTINS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:27:28