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

Django技术问题:如何将单个字段设为折叠面板标题,其余字段为内容?

优化手风琴表格布局,遵循DRY原则的解决方案

嘿,我懂你现在的痛点——重复循环数据集不仅不符合DRY(Don't Repeat Yourself)原则,还会让代码冗余、维护起来麻烦。咱们只需要先把object.rate_set.all的数据按frequency字段分组,就能用一次循环搞定手风琴的标题和对应的内容啦!

步骤1:在视图层完成数据分组(推荐方案)

先在视图里对数据进行排序+分组,确保相同frequency的项被归类到一起,这样模板里就能直接用分组后的结果:

from itertools import groupby

# 先按frequency排序,保证groupby能正确分组
sorted_rates = object.rate_set.all().order_by('frequency')
# 按frequency字段分组,得到(频率值, 对应rate对象列表)的结构
grouped_rates = groupby(sorted_rates, key=lambda rate: rate.frequency)
# 转成列表方便模板遍历
frequency_groups = [(freq, list(rate_items)) for freq, rate_items in grouped_rates]

把frequency_groups传到模板里就可以了。

步骤2:模板里一次循环生成手风琴

现在模板里只需要两层循环(外层循环分组,内层循环当前分组下的产品和价格),完全避免重复遍历整个rate集合:

<div class="accordion" id="frequencyAccordion">
  {% for freq, rate_items in frequency_groups %}
    <div class="accordion-item">
      <h2 class="accordion-header" id="heading-{{ forloop.counter }}">
        <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-{{ forloop.counter }}">
          {{ freq }} <!-- 手风琴标题:frequency值 -->
        </button>
      </h2>
      <div id="collapse-{{ forloop.counter }}" class="accordion-collapse collapse" aria-labelledby="heading-{{ forloop.counter }}" data-bs-parent="#frequencyAccordion">
        <div class="accordion-body">
          <table class="table">
            <tbody>
              {% for item in rate_items %}
                <tr>
                  <td>{{ item.product }}</td>
                  <td>{{ item.price }}</td>
                </tr>
              {% endfor %}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  {% endfor %}
</div>

为什么这个方案更好?

  • 只执行一次数据库查询,排序在数据库层面完成,性能更优
  • 模板代码逻辑清晰,完全遵循DRY原则,没有重复遍历数据集
  • 后续维护时,只需要修改一处逻辑即可,降低出错概率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:31:30