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

如何在Django模板中按序渲染OrderedDict数据为表格

我之前也遇到过类似的Django模板渲染分组表格的需求,给你两种可行的方案,优先推荐第一种——逻辑更清晰,调试也更方便:


方案一:视图层预处理数据(推荐)

与其在模板里折腾复杂的逻辑,不如先在Python视图里把你的OrderedDict数据转换成模板需要的结构化分组格式,再传给模板渲染。这样模板只需要负责展示,代码更易维护。

假设你的数据里,quantity_balance为正代表买入(Buys)、为负代表卖出(Sells),我们可以按日期聚合每个时段的买入、卖出和总余额:

from collections import OrderedDict
from django.shortcuts import render

def your_view(request):
    # 这是你已有的OrderedDict数据
    original_table = OrderedDict([
        ('1', {'date': '2024-01-01', 'document': 'INV-001', 'quantity_balance': 100}),
        ('2', {'date': '2024-01-01', 'document': 'INV-002', 'quantity_balance': -50}),
        ('3', {'date': '2024-01-02', 'document': 'INV-003', 'quantity_balance': 200}),
    ])

    # 按日期分组,整理Buys、Sells、Total数据
    grouped_data = OrderedDict()
    for item in original_table.values():
        date = item['date']
        # 初始化该日期的分组结构
        if date not in grouped_data:
            grouped_data[date] = {'buys': [], 'sells': [], 'total': 0}
        
        # 归类买入/卖出数据
        if item['quantity_balance'] > 0:
            grouped_data[date]['buys'].append({
                'doc': item['document'],
                'qty': item['quantity_balance']
            })
        else:
            grouped_data[date]['sells'].append({
                'doc': item['document'],
                'qty': abs(item['quantity_balance'])
            })
        # 累计总余额
        grouped_data[date]['total'] += item['quantity_balance']

    # 把处理好的分组数据传给模板
    return render(request, 'your_template.html', {'grouped_table': grouped_data})

然后在模板里直接渲染结构化数据即可:

<table border="1" cellpadding="8" cellspacing="0">
    <thead>
        <tr>
            <th>Date</th>
            <th>Buys</th>
            <th>Sells</th>
            <th>Total Balance</th>
        </tr>
    </thead>
    <tbody>
        {% for date, data in grouped_table.items %}
        <tr>
            <td>{{ date }}</td>
            <td>
                {% for buy in data.buys %}
                <p>{{ buy.doc }}: {{ buy.qty }}</p>
                {% empty %}
                <p>-</p>
                {% endfor %}
            </td>
            <td>
                {% for sell in data.sells %}
                <p>{{ sell.doc }}: {{ sell.qty }}</p>
                {% empty %}
                <p>-</p>
                {% endfor %}
            </td>
            <td><strong>{{ data.total }}</strong></td>
        </tr>
        {% endfor %}
    </tbody>
</table>

方案二:自定义模板过滤器(适合简单过滤场景)

如果你坚持要在模板里处理数据,可能是之前的自定义标签写法有问题。可以试试写一个专用的过滤器来筛选Buys/Sells数据:

  1. 在你的app目录下创建templatetags文件夹,里面新建table_filters.py和__init__.py文件:
from django import template

register = template.Library()

@register.filter
def filter_transactions(items, trans_type):
    """筛选买入或卖出数据,trans_type传'buys'或'sells'"""
    filtered = []
    for item in items:
        if trans_type == 'buys' and item['quantity_balance'] > 0:
            filtered.append(item)
        elif trans_type == 'sells' and item['quantity_balance'] < 0:
            # 复制并转换负数为正数显示
            item_copy = item.copy()
            item_copy['quantity_balance'] = abs(item_copy['quantity_balance'])
            filtered.append(item_copy)
    return filtered

@register.filter
def calculate_total(items):
    """计算总余额"""
    return sum(item['quantity_balance'] for item in items)
  1. 在模板里加载过滤器并使用:
{% load table_filters %}

<table border="1" cellpadding="8" cellspacing="0">
    <thead>
        <tr>
            <th>Date</th>
            <th>Buys</th>
            <th>Sells</th>
            <th>Total Balance</th>
        </tr>
    </thead>
    <tbody>
        <!-- 这里假设你按日期去重后遍历,或者直接遍历原始数据的日期 -->
        {% for date in unique_dates %}
        {% with date_items=table.values|filter_by_date:date %} {# 你还需要补充一个按日期过滤的过滤器,写法类似上面的filter_transactions #}
        <tr>
            <td>{{ date }}</td>
            <td>
                {% for buy in date_items|filter_transactions:'buys' %}
                <p>{{ buy.document }}: {{ buy.quantity_balance }}</p>
                {% empty %}
                <p>-</p>
                {% endfor %}
            </td>
            <td>
                {% for sell in date_items|filter_transactions:'sells' %}
                <p>{{ sell.document }}: {{ sell.quantity_balance }}</p>
                {% empty %}
                <p>-</p>
                {% endfor %}
            </td>
            <td><strong>{{ date_items|calculate_total }}</strong></td>
        </tr>
        {% endwith %}
        {% endfor %}
    </tbody>
</table>

小提示

  • 优先用方案一,Python处理数据比模板标签灵活得多,调试起来也更方便;
  • 如果你的分组逻辑和我假设的(按正负判断买卖)不一样,只需要修改视图里的归类条件即可;
  • OrderedDict在Django模板里可以直接用{% for key, value in table.items %}迭代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:31:39