制作报表

导出Excel报表

报表就是用表格、图表等格式来动态显示数据,所以有人用这样的公式来描述报表:

  1. 报表 = 多样的格式 + 动态的数据

有很多的三方库支持在Python程序中写Excel文件,包括xlwtxlwingsopenpyxlxlswriter等,其中的xlwt虽然只支持写xls格式的Excel文件,但在性能方面的表现还是不错的。下面我们就以xlwt为例,来演示如何在Django项目中导出Excel报表。

安装xlwt

  1. pip install xlwt

导出包含所有老师信息的Excel表格的视图函数。

  1. def export_teachers_excel(request):
  2. # 创建工作簿
  3. wb = xlwt.Workbook()
  4. # 添加工作表
  5. sheet = wb.add_sheet('老师信息表')
  6. # 查询所有老师的信息
  7. queryset = Teacher.objects.all()
  8. # 向Excel表单中写入表头
  9. colnames = ('姓名', '介绍', '好评数', '差评数', '学科')
  10. for index, name in enumerate(colnames):
  11. sheet.write(0, index, name)
  12. # 向单元格中写入老师的数据
  13. props = ('name', 'detail', 'good_count', 'bad_count', 'subject')
  14. for row, teacher in enumerate(queryset):
  15. for col, prop in enumerate(props):
  16. value = getattr(teacher, prop, '')
  17. if isinstance(value, Subject):
  18. value = value.name
  19. sheet.write(row + 1, col, value)
  20. # 保存Excel
  21. buffer = BytesIO()
  22. wb.save(buffer)
  23. # 将二进制数据写入响应的消息体中并设置MIME类型
  24. resp = HttpResponse(buffer.getvalue(), content_type='application/vnd.ms-excel')
  25. # 中文文件名需要处理成百分号编码
  26. filename = quote('老师.xls')
  27. # 通过响应头告知浏览器下载该文件以及对应的文件名
  28. resp['content-disposition'] = f'attachment; filename*=utf-8\'\'{filename}'
  29. return resp

映射URL。

  1. urlpatterns = [
  2. path('excel/', views.export_teachers_excel),
  3. ]

导出PDF报表

在Django项目中,如果需要导出PDF报表,可以借助三方库reportlab来生成PDF文件的内容,再将文件的二进制数据输出给浏览器并指定MIME类型为application/pdf,具体的代码如下所示。

  1. def export_pdf(request: HttpRequest) -> HttpResponse:
  2. buffer = io.BytesIO()
  3. pdf = canvas.Canvas(buffer)
  4. pdf.setFont("Helvetica", 80)
  5. pdf.setFillColorRGB(0.2, 0.5, 0.3)
  6. pdf.drawString(100, 550, 'hello, world!')
  7. pdf.showPage()
  8. pdf.save()
  9. resp = HttpResponse(buffer.getvalue(), content_type='application/pdf')
  10. resp['content-disposition'] = 'inline; filename="demo.pdf"'
  11. return resp

关于如何用reportlab定制PDF报表的内容,可以参考reportlab的官方文档

生成前端统计图表

如果项目中需要生成前端统计图表,可以使用百度的ECharts。具体的做法是后端通过提供数据接口返回统计图表所需的数据,前端使用ECharts来渲染出柱状图、折线图、饼图、散点图等图表。例如我们要生成一个统计所有老师好评数和差评数的报表,可以按照下面的方式来做。

  1. def get_teachers_data(request):
  2. queryset = Teacher.objects.all()
  3. names = [teacher.name for teacher in queryset]
  4. good_counts = [teacher.good_count for teacher in queryset]
  5. bad_counts = [teacher.bad_count for teacher in queryset]
  6. return JsonResponse({'names': names, 'good': good_counts, 'bad': bad_counts})

映射URL。

  1. urlpatterns = [
  2. path('teachers_data/', views.get_teachers_data),
  3. ]

使用ECharts生成柱状图。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>老师评价统计</title>
  6. </head>
  7. <body>
  8. <div id="main" style="width: 600px; height: 400px"></div>
  9. <p>
  10. <a href="/">返回首页</a>
  11. </p>
  12. <script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js"></script>
  13. <script>
  14. var myChart = echarts.init(document.querySelector('#main'))
  15. fetch('/teachers_data/')
  16. .then(resp => resp.json())
  17. .then(json => {
  18. var option = {
  19. color: ['#f00', '#00f'],
  20. title: {
  21. text: '老师评价统计图'
  22. },
  23. tooltip: {},
  24. legend: {
  25. data:['好评', '差评']
  26. },
  27. xAxis: {
  28. data: json.names
  29. },
  30. yAxis: {},
  31. series: [
  32. {
  33. name: '好评',
  34. type: 'bar',
  35. data: json.good
  36. },
  37. {
  38. name: '差评',
  39. type: 'bar',
  40. data: json.bad
  41. }
  42. ]
  43. }
  44. myChart.setOption(option)
  45. })
  46. </script>
  47. </body>
  48. </html>

运行效果如下图所示。

Day45 - 报表和日志 - 图1