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

Django模板循环中正确显示list对应元素的问题求助

问题分析

你遇到的核心问题是模板中没有将transactions和main列表的元素一一对应:在遍历每个交易记录时,你嵌套遍历了整个main列表,导致每个交易都会重复输出main的所有元素,而非仅显示当前交易对应的余额值。

解决方案

提供两种可行的解决方式,推荐第一种(逻辑更清晰、易维护):

方法1:在视图中打包交易与对应余额

修改views.py,将transactions和main中的元素一一配对成元组,再传递给模板:

def cust_ledger(request, pk):
    cust = Customer.objects.get(id=pk)
    dbs = [Issue, Receive, SalesReturn]

    transactions = sorted(
        [m
         for db in dbs
         for m in db.objects.filter(customer=cust).order_by('date_time')],
        key=attrgetter('date_time')
    )

    quant_bal = 0
    amt_bal = 0
    sb_q = 0
    rb_q = 0
    sr_q = 0
    main = []

    for tx in transactions:
        if tx.tt == 'SB':
            sb_q += tx.quantity
            main.append(sb_q)
            quant_bal += tx.quantity
            amt_bal += tx.amount
        elif tx.tt == 'RB':
            rb_q = sb_q - tx.quantity
            main.append(rb_q)
            quant_bal -= tx.quantity
            amt_bal -= tx.amount
        else:
            sr_q = sb_q - tx.quantity
            main.append(sr_q)
            quant_bal -= tx.quantity
            amt_bal -= tx.amount

    # 打包交易与对应余额为元组列表
    transactions_with_balance = list(zip(transactions, main))
    
    context = {
        'transactions_with_balance': transactions_with_balance, 
        'cust': cust, 
        'quant_bal': quant_bal, 
        'amt_bal': amt_bal,
        'sb_q': sb_q, 'rb_q': rb_q, 'sr_q': sr_q
    }

    return render(request, 'customer/ledger.html', context)

然后修改模板,遍历打包后的列表:

<div class="flex-wrap">
    {% for tx, balance in transactions_with_balance %}
        {% if tx.tt == 'SB' %}
            <a href="{% url 'issue-detail' tx.id %}">
        {% elif tx.tt == 'RB' %}
            <a href="{% url 'rec-detail' tx.id %}">
        {% else %}
            <a href="{% url 'sr-detail' tx.id %}">
        {% endif %}
                <div class="bar name">
                    <p class="p1">{{tx.date_time| date:"F j, Y"}}</p>
                    <p class="p2">{{tx.tt}}</p>
                    <p class="p3">{{tx.id}}</p>
                    <p class="p4">{{tx.voucher}}</p>

                    {% if tx.tt == 'SB' %}
                        <p class="p5 ic_q">{{tx.quantity}}g</p>
                        <p class="p6 ic_c">{{tx.amount}} SAR</p>
                        <p class="p5 rc_q">-</p>
                        <p class="p6 rc_c">-</p>
                    {% elif tx.tt == 'RB' %} 
                        <p class="p5 ic_q">-</p>
                        <p class="p6 ic_c">-</p>
                        <p class="p5 rc_q">{{tx.quantity}}g</p>
                        <p class="p6 rc_c">{{tx.amount}} SAR</p>
                    {% else %}
                        <p class="p5 ic_q">-</p>
                        <p class="p6 ic_c">-</p>
                        <p class="p5 rc_q">{{tx.quantity}}g</p>
                        <p class="p6 rc_c">{{tx.amount}} SAR</p>
                    {% endif %}

                    <!-- 直接使用配对好的balance值 -->
                    <p class="p7">{{balance}}g</p>
                    {% if tx.tt == 'SB' %}
                        <p class="p8">{{sb_cash_bal}} SAR</p>
                    {% else %}
                        <p class="p8">{{rb_cash_bal}} SAR</p>
                    {% endif %}
                </div>
            </a>                   
    {% endfor %}
    <div class="bar final">
        <h3>Total</h3>
        <p class="p9">{{quant_bal}}g</p>
        <p class="p10">{{amt_bal}} SAR</p>
    </div>    
</div>

方法2:在模板中使用循环索引

如果不想修改视图,可以利用Django模板的forloop.counter0(从0开始的索引)来获取main中对应位置的元素:

<div class="flex-wrap">
    {% for tx in transactions %}
        {% if tx.tt == 'SB' %}
            <a href="{% url 'issue-detail' tx.id %}">
        {% elif tx.tt == 'RB' %}
            <a href="{% url 'rec-detail' tx.id %}">
        {% else %}
            <a href="{% url 'sr-detail' tx.id %}">
        {% endif %}
                <div class="bar name">
                    <!-- 省略其他不变的代码 -->

                    <!-- 通过索引获取对应main元素 -->
                    {% with balance=main|slice:":forloop.counter"|last %}
                        <p class="p7">{{balance}}g</p>
                    {% endwith %}
                    {% if tx.tt == 'SB' %}
                        <p class="p8">{{sb_cash_bal}} SAR</p>
                    {% else %}
                        <p class="p8">{{rb_cash_bal}} SAR</p>
                    {% endif %}
                </div>
            </a>                   
    {% endfor %}
    <!-- 省略总计部分 -->
</div>

注:slice:":forloop.counter"取列表前forloop.counter个元素,再用last获取最后一个,等价于取main[forloop.counter0](因为forloop.counter从1开始,forloop.counter0从0开始)。

额外说明
  • 模板中sb_cash_bal和rb_cash_bal变量未在视图中传递,需要补充对应的计算逻辑或修正变量名。
  • 第一种方法符合Django的MVC设计思想,所有数据预处理在视图中完成,模板仅负责展示,逻辑更清晰。

内容的提问来源于stack exchange,提问作者pip install logic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:17:00