報表就是用表格、圖表等格式來動態顯示資料,所以有人用這樣的公式來描述報表:
報表 = 多樣的格式 + 動態的資料
有很多的三方庫支援在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),
]
在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>
執行效果如下圖所示。