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
相关产品推荐
相关产品推荐

