Flask模板字典键匹配合并问题:API数据表格渲染异常
解决Flask模板表格渲染重复行问题
看起来你遇到的问题是嵌套循环导致同一个stamp条目被多次渲染——因为一个stamp(比如LG)在api1里对应多个价格条目(LGUK、LGUS),每次匹配成功都会生成一行,所以stamp和free会重复出现,造成数据混乱。
问题根源
你的模板先遍历api2['stock'],再遍历api1,每匹配到一次就输出一行。比如LG这个stamp,会和LGUK、LGUS各匹配一次,于是生成两行完全相同的LG和472,只是价格不同,这就是重复行的来源。
解决方案一:后端预处理数据(推荐)
最清晰易维护的方式是在Flask视图函数里先把两个API的数据合并成结构化列表,模板只需要简单循环即可:
# 在Flask路由函数中添加数据预处理逻辑 price_map = {} # 先把api1的价格按stamp分组 for item in api1: stamp = item['size'][:-2].strip() # 提取SM/LG/XL这类前缀 if stamp not in price_map: price_map[stamp] = [] price_map[stamp].append(item['price']) # 合并库存与价格数据 merged_data = [] for stock_item in api2['stock']: stamp = stock_item['stamp'] # 匹配对应价格,没有则显示N/A if stamp in price_map: for price in price_map[stamp]: merged_data.append({ 'stamp': stamp, 'free': stock_item['free'], 'price': price }) else: merged_data.append({ 'stamp': stamp, 'free': stock_item['free'], 'price': 'N/A' }) # 将merged_data传给模板 return render_template('home.html', merged_data=merged_data)
然后模板代码简化为:
<tbody> {% for item in merged_data %} <tr> <td>{{ item.stamp }}</td> <td>{{ item.free }}</td> <td>{{ item.price }}</td> </tr> {% endfor %} </tbody>
解决方案二:模板中用rowspan合并重复单元格
如果不想修改后端代码,可以用HTML的rowspan属性让同一stamp和free跨多行显示,避免视觉重复:
<tbody> {% for data2 in api2['stock'] %} {% set matching_prices = [] %} {% for data1 in api1 %} {% if data2['stamp'] == data1['size'][:-2].strip() %} {% do matching_prices.append(data1['price']) %} {% endif %} {% endfor %} {% if matching_prices %} {% for idx, price in enumerate(matching_prices) %} <tr> {% if idx == 0 %} <td rowspan="{{ matching_prices|length }}">{{ data2.stamp }}</td> <td rowspan="{{ matching_prices|length }}">{{ data2.free }}</td> {% endif %} <td>{{ price }}</td> </tr> {% endfor %} {% else %} <tr> <td>{{ data2.stamp }}</td> <td>{{ data2.free }}</td> <td>N/A</td> </tr> {% endif %} {% endfor %} </tbody>
注意:使用{% do %}标签需要先在Flask中启用扩展:
from flask import Flask app = Flask(__name__) app.jinja_options['extensions'].append('jinja2.ext.do')
补充:按单个size条目渲染
如果你的需求是为每个api1的size(比如SMUS、LGUK)单独生成一行,关联对应库存,可以调整模板逻辑:
<tbody> {% for data1 in api1 %} {% set stamp = data1['size'][:-2].strip() %} {% set stock_item = api2['stock']|selectattr('stamp', 'equalto', stamp)|first %} <tr> <td>{{ stamp }}</td> <td>{{ stock_item.free if stock_item else 'N/A' }}</td> <td>{{ data1.price }}</td> </tr> {% endfor %} </tbody>
内容的提问来源于stack exchange,提问作者user3408056
相关产品推荐
相关产品推荐

