ITPub博客

首页 > > > Python学习教程:报表和日志

Python学习教程:报表和日志

作者:u_151d1ef45539 时间:2019-08-30 09:57:34 0 删除 编辑

Python学习教程:报表和日志

导出Excel报表

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

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

有很多的三方库支持在Python程序中写Excel文件,包括xlwt、xlwings、openpyxl、xlswriter、pandas等,其中的xlwt虽然只支持写xls格式的Excel文件,但在性能方面的表现还是不错的。下面我们就以xlwt为例,来演示如何在Django项目中导出Excel报表,例如导出一个包含所有老师信息的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="{filename}"'
 return resp

映射URL。

urlpatterns = [
 # 此处省略上面的代码
 path('excel/', views.export_teachers_excel),
 # 此处省略下面的代码
]


生成前端统计图表

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

def get_teachers_data(request):
 # 查询所有老师的信息(注意:这个地方稍后也需要优化)
 queryset = Teacher.objects.all()
 # 用生成式将老师的名字放在一个列表中
 names = [teacher.name for teacher in queryset]
 # 用生成式将老师的好评数放在一个列表中
 good = [teacher.good_count for teacher in queryset]
 # 用生成式将老师的差评数放在一个列表中
 bad = [teacher.bad_count for teacher in queryset]
 # 返回JSON格式的数据
 return JsonResponse({'names': names, 'good': good, 'bad': bad})
映射URL。

urlpatterns = [
 # 此处省略上面的代码
 path('teachers_data/', views.export_teachers_excel),
 # 此处省略下面的代码
]
使用ECharts生成柱状图。

<!DOCTYPE html>
<html>
<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>

运行效果如下图所示。


配置日志

项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。要做好这两件事件,我们需要为Django项目配置日志。

Django的日志配置基本可以参照官方文档再结合项目实际需求来进行,这些内容基本上可以从官方文档上复制下来,然后进行局部的调整即可,下面给出一些参考配置。

LOGGING = {
 'version': 1,
 # 是否禁用已经存在的日志器
 'disable_existing_loggers': False,
 # 日志格式化器
 'formatters': {
 'simple': {
 'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
 'datefmt': '%Y-%m-%d %H:%M:%S',
 },
 'verbose': {
 'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
 '%(module)s.%(funcName)s line %(lineno)d: %(message)s',
 'datefmt': '%Y-%m-%d %H:%M:%S',
 }
 },
 # 日志过滤器
 'filters': {
 # 只有在Django配置文件中DEBUG值为True时才起作用
 'require_debug_true': {
 '()': 'django.utils.log.RequireDebugTrue',
 },
 },
 # 日志处理器
 'handlers': {
 # 输出到控制台
 'console': {
 'class': 'logging.StreamHandler',
 'level': 'DEBUG',
 'filters': ['require_debug_true'],
 'formatter': 'simple',
 },
 # 输出到文件(每周切割一次)
 'file1': {
 'class': 'logging.handlers.TimedRotatingFileHandler',
 'filename': 'access.log',
 'when': 'W0',
 'backupCount': 12,
 'formatter': 'simple',
 'level': 'INFO',
 },
 # 输出到文件(每天切割一次)
 'file2': {
 'class': 'logging.handlers.TimedRotatingFileHandler',
 'filename': 'error.log',
 'when': 'D',
 'backupCount': 31,
 'formatter': 'verbose',
 'level': 'WARNING',
 },
 },
 # 日志器记录器
 'loggers': {
 'django': {
 # 需要使用的日志处理器
 'handlers': ['console', 'file1', 'file2'],
 # 是否向上传播日志信息
 'propagate': True,
 # 日志级别(不一定是最终的日志级别)
 'level': 'DEBUG',
 },
 }
}

大家可能已经注意到了,上面日志配置中的formatters是日志格式化器,它代表了如何格式化输出日志,其中格式占位符分别表示:

  • %(name)s - 记录器的名称
  • %(levelno)s - 数字形式的日志记录级别
  • %(levelname)s - 日志记录级别的文本名称
  • %(filename)s - 执行日志记录调用的源文件的文件名称
  • %(pathname)s - 执行日志记录调用的源文件的路径名称
  • %(funcName)s - 执行日志记录调用的函数名称
  • %(module)s - 执行日志记录调用的模块名称
  • %(lineno)s - 执行日志记录调用的行号
  • %(created)s - 执行日志记录的时间
  • %(asctime)s - 日期和时间
  • %(msecs)s - 毫秒部分
  • %(thread)d - 线程ID(整数)
  • %(threadName)s - 线程名称
  • %(process)d - 进程ID (整数)

日志配置中的handlers用来指定日志处理器,简单的说就是指定将日志输出到控制台还是文件又或者是网络上的服务器,可用的处理器包括:

  • logging.StreamHandler(stream=None) - 可以向类似与sys.stdout或者sys.stderr的任何文件对象输出信息
  • logging.FileHandler(filename, mode='a', encoding=None, delay=False) - 将日志消息写入文件
  • logging.handlers.DatagramHandler(host, port) - 使用UDP协议,将日志信息发送到指定主机和端口的网络主机上
  • logging.handlers.HTTPHandler(host, url) - 使用HTTP的GET或POST方法将日志消息上传到一台HTTP 服务器
  • logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False) - 将日志消息写入文件,如果文件的大小超出maxBytes指定的值,那么将重新生成一个文件来记录日志
  • logging.handlers.SocketHandler(host, port) - 使用TCP协议,将日志信息发送到指定主机和端口的网络主机上
  • logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0) - 将日志输出到指定的邮件地址
  • logging.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True) - 将日志输出到内存指定的缓冲区中

上面每个日志处理器都指定了一个名为“level”的属性,它代表了日志的级别,不同的日志级别反映出日志中记录信息的严重性。Python中定义了六个级别的日志,按照从低到高的顺序依次是:NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL。

最后配置的日志记录器是用来真正输出日志的,Django框架提供了如下所示的内置记录器:

  • django - 在Django层次结构中的所有消息记录器
  • django.request - 与请求处理相关的日志消息。5xx响应被视为错误消息;4xx响应被视为为警告消息
  • django.server - 与通过runserver调用的服务器所接收的请求相关的日志消息。5xx响应被视为错误消息;4xx响应被记录为警告消息;其他一切都被记录为INFO
  • django.template - 与模板渲染相关的日志消息
  • django.db.backends - 有与数据库交互产生的日志消息,如果希望显示ORM框架执行的SQL语句,就可以使用该日志记录器。

日志记录器中配置的日志级别有可能不是最终的日志级别,因为还要参考日志处理器中配置的日志级别,取二者中级别较高者作为最终的日志级别。




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69927053/viewspace-3156438/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-07-31

  • 博文量
    155
  • 访问量
    256