Flask读取Excel对接Chart.js报TypeError: string indices must be integers
问题说明
使用Python Flask框架开发时,需实现读取Excel文件数据、将各列内容传递至HTML页面并借助chart.js库绘制图表的功能,运行过程中触发TypeError: string indices must be integers报错。
涉及的Excel数据样例:
| student | result |
|---|---|
| 0.2 | 14 |
| 0.3 | 15 |
| 0.4 | 16 |
| 0.5 | 19 |
报错原因
代码存在两处核心错误,直接触发该类型报错:
- 上传文件获取方式错误:
request.form只能拿到表单提交的普通字符串值,这里取到的file是上传文件的文件名字符串,不是文件对象本身,上传文件需要从request.files中获取。 - 变量引用错误:pandas读取Excel后的内容存在
data变量中,但取列时错误使用了存字符串的file变量,对字符串执行['student']这类键名索引操作时,Python要求字符串索引必须为整数,因此抛出类型错误。
原错误后端代码:
@app.route('/data',methods = ['GET','POST']) def data(): if request.method == 'POST': file = request.form['upload-file'] data=pd.read_excel(file) labels=list(file['student']) # 这里对字符串file做键索引,直接触发报错 values=list(file['result']) return render_template('graph.html',labels=labels ,values=values)
修复方案
- 修正文件获取逻辑,从
request.files拿到上传的文件对象传给pandas读取。 - 修正变量引用,从pandas生成的DataFrame对象中取对应列数据。
- 传递数据到前端时,用
json.dumps把Python列表转为JSON格式,避免JS解析异常。 - 补充GET请求的返回逻辑,避免直接访问路由时出现500错误。
- 前端上传表单必须添加
enctype="multipart/form-data"属性,否则无法正常传输文件。
修复后的后端代码:
from flask import request, render_template import pandas as pd import json @app.route('/data',methods = ['GET','POST']) def data(): if request.method == 'POST': # 从files接口获取上传的文件对象 upload_file = request.files['upload-file'] # 读取Excel内容为DataFrame df = pd.read_excel(upload_file) # 从DataFrame取对应列转列表,序列化后传给前端 labels = json.dumps(df['student'].tolist()) values = json.dumps(df['result'].tolist()) return render_template('graph.html', labels=labels, values=values) # GET请求返回上传页面 return render_template('upload.html')
可用的上传表单代码片段:
<form action="/data" method="POST" enctype="multipart/form-data"> <input type="file" name="upload-file" accept=".xlsx,.xls" required> <button type="submit">上传并生成图表</button> </form>
前端图表渲染代码片段(需提前在页面引入chart.js库):
<canvas id="myChart" width="600" height="300"></canvas> <script> const ctx = document.getElementById('myChart').getContext('2d'); const myChart = new Chart(ctx, { type: 'line', data: { labels: {{ labels|safe }}, datasets: [{ label: '结果值', data: {{ values|safe }}, borderColor: '#2196F3', fill: false, tension: 0.2 }] } }); </script>
内容的提问来源于stack exchange,提问作者Rehan Akhtar
相关产品推荐
相关产品推荐

