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

在Django中高效展示标签筛选后文章的关联标签列表

解决Django多对多关联的N+1查询问题

当前代码里,prefetch_related('publications')只预取了指定标签下的所有文章,但每篇文章关联的tags并没有被预取,所以在模板里遍历publication.tags时,每篇文章都会触发一次单独的数据库查询,也就是典型的N+1问题。

直接用嵌套预取就能解决这个问题,借助Django的Prefetch对象,在预取文章的同时,把每篇文章的标签也一起预取出来:

修改后的views.py代码:

# views.py
from .models import Tag, Publication
from django.shortcuts import get_object_or_404, render
from django.db.models import Prefetch


def publications_tagged(request, name):
    tag = get_object_or_404(
        Tag.objects.prefetch_related(
            # 预取当前标签下的文章,同时预取每篇文章的所有关联标签
            Prefetch(
                'publications',
                queryset=Publication.objects.prefetch_related('tags')
            )
        ),
        name=name
    )
    return render(request, 'myapp/tagged_questions.html', {'tag': tag})

效果说明

修改后,Django只会执行3次数据库查询:

  1. 查询指定名称的Tag
  2. 查询该Tag关联的所有Publication
  3. 查询这些Publication对应的所有Tag,并自动关联到对应的文章

模板里可以正常遍历文章和它们的标签,不会触发额外查询:

<!-- tagged_questions.html -->
<h1>标签 {{ tag.name }} 下的文章</h1>
{% for publication in tag.publications %}
    <div class="publication-item">
        <h3>{{ publication.name }}</h3>
        <p>{{ publication.text|truncatewords:30 }}</p>
        <div class="tag-list">
            {% for tag in publication.tags %}
                <span class="tag">{{ tag.name }}</span>
            {% endfor %}
        </div>
    </div>
{% endfor %}

这种方式和StackOverflow的标签列表优化思路一致,一次性拉取所有需要的关联数据,避免反复查询数据库,大幅提升页面渲染效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:50:44