Python 100 Days Day45 Make Sheet
21 Sep 2022 | beginner pythonauthor: jackfrued
制作報表
導出Excel報表
報表就是用表格、圖表等格式來動態顯示數據,所以有人用這樣的公式來描述報表:
報表 = 多樣的格式 + 動態的數據
有很多的三方庫支持在Python程序中寫Excel文件,包括xlwt、xlwings、openpyxl、xlswriter等,其中的xlwt雖然只支持寫xls格式的Excel文件,但在性能方面的表現還是不錯的。下面我們就以xlwt為例,來演示如何在Django項目中導出Excel報表。
安裝xlwt。
pip install xlwt
導出包含所有老師信息的Excel表格的視圖函數。
def export_teachers_excel(request):
# 創建工作簿
wb = xlwt.Workbook()
# 添加工作表
sheet = wb.add_sheet('老師信息表')
# 查詢所有老師的信息
queryset = Teacher.objects.all()
# 向Excel表單中寫入表頭
colnames = ('姓名', '介紹', '好評數', '差評數', '學科')
for index, name in enumerate(colnames):
sheet.write(0, index, name)
# 向單元格中寫入老師的數據
props = ('name', 'detail', 'good_count', 'bad_count', 'subject')
for row, teacher in enumerate(queryset):
for col, prop in enumerate(props):
value = getattr(teacher, prop, '')
if isinstance(value, Subject):
value = value.name
sheet.write(row + 1, col, value)
# 保存Excel
buffer = BytesIO()
wb.save(buffer)
# 將二進制數據寫入響應的消息體中並設置MIME類型
resp = HttpResponse(buffer.getvalue(), content_type='application/vnd.ms-excel')
# 中文文件名需要處理成百分號編碼
filename = quote('老師.xls')
# 通過響應頭告知瀏覽器下載該文件以及對應的文件名
resp['content-disposition'] = f'attachment; filename*=utf-8\'\'{filename}'
return resp
映射URL。
urlpatterns = [
path('excel/', views.export_teachers_excel),
]
導出PDF報表
在Django項目中,如果需要導出PDF報表,可以借助三方庫reportlab來生成PDF文件的內容,再將文件的二進制數據輸出給瀏覽器並指定MIME類型為application/pdf,具體的代碼如下所示。
def export_pdf(request: HttpRequest) -> HttpResponse:
buffer = io.BytesIO()
pdf = canvas.Canvas(buffer)
pdf.setFont("Helvetica", 80)
pdf.setFillColorRGB(0.2, 0.5, 0.3)
pdf.drawString(100, 550, 'hello, world!')
pdf.showPage()
pdf.save()
resp = HttpResponse(buffer.getvalue(), content_type='application/pdf')
resp['content-disposition'] = 'inline; filename="demo.pdf"'
return resp
關於如何用reportlab定制PDF報表的內容,可以參考reportlab的官方文檔。
生成前端統計圖表
如果項目中需要生成前端統計圖表,可以使用百度的ECharts。具體的做法是後端通過提供數據接口返回統計圖表所需的數據,前端使用ECharts來渲染出柱狀圖、折線圖、餅圖、散點圖等圖表。例如我們要生成一個統計所有老師好評數和差評數的報表,可以按照下面的方式來做。
def get_teachers_data(request):
queryset = Teacher.objects.all()
names = [teacher.name for teacher in queryset]
good_counts = [teacher.good_count for teacher in queryset]
bad_counts = [teacher.bad_count for teacher in queryset]
return JsonResponse({'names': names, 'good': good_counts, 'bad': bad_counts})
映射URL。
urlpatterns = [
path('teachers_data/', views.get_teachers_data),
]
使用ECharts生成柱狀圖。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>老師評價統計</title>
</head>
<body>
<div id="main" style="width: 600px; height: 400px"></div>
<p>
<a href="/">返回首頁</a>
</p>
<script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js"></script>
<script>
var myChart = echarts.init(document.querySelector('#main'))
fetch('/teachers_data/')
.then(resp => resp.json())
.then(json => {
var option = {
color: ['#f00', '#00f'],
title: {
text: '老師評價統計圖'
},
tooltip: {},
legend: {
data:['好評', '差評']
},
xAxis: {
data: json.names
},
yAxis: {},
series: [
{
name: '好評',
type: 'bar',
data: json.good
},
{
name: '差評',
type: 'bar',
data: json.bad
}
]
}
myChart.setOption(option)
})
</script>
</body>
</html>
運行效果如下圖所示。

Comments