Django实践-07日志调试,Django-Debug-Toolbar配置与sql优化

简介: Django实践-07日志调试,Django-Debug-Toolbar配置与sql优化

image.png


Django实践-07日志调试与sql优化


官网:https://www.djangoproject.com/

博客:https://www.liujiangblog.com/

本博客内容参考git:https://gitcode.net/mirrors/jackfrued/Python-100-Days 一些细节问题,大家可以查看git连接。本文主要的改变为把代码升级为django4.1版本。


Django静态文件问题备注:

参考:

Django测试开发-20-settings.py中templates配置,使得APP下的模板以及根目录下的模板均可生效

解决django 多个APP时 static文件的问题


django配置app中的静态文件步骤

Django多APP加载静态文件


django.short包参考:https://docs.djangoproject.com/en/4.1/topics/http/shortcuts/


配置日志


参考:

https://docs.djangoproject.com/zh-hans/4.1/topics/logging/#configuring-logging

https://docs.python.org/3/library/logging.config.html#logging-config-dictschema


项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;

项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。

与此同时,采集日志数据也是为网站做数字化运营奠定一个基础,通过对系统运行日志的分析,我们可以监测网站的流量以及流量分布,同时还可以挖掘出用户的使用习惯和行为模式。


Although Django’s logging configuration works out of the box, you can control exactly how your logs are sent to various destinations - to log files, external services, email and so on - with some additional configuration.

虽然Django的日志配置是开箱即用的,但是你可以通过一些额外的配置来控制你的日志如何被发送到不同的目的地——日志文件、外部服务、电子邮件等等。


你可以配置:


logger mappings, to determine which records are sent to which handlers

记录器映射,以确定将哪些记录发送到哪些处理程序

handlers, to determine what they do with the records they receive

处理程序,以确定如何处理接收到的记录

filters, to provide additional control over the transfer of records, and even modify records in-place

过滤器,以提供对记录传输的额外控制,甚至就地修改记录

formatters, to convert LogRecord objects to a string or other form for consumption by human beings or another system

格式化程序,用于将LogRecord对象转换为字符串或其他形式以供人类或其他系统使用


日志配置说明1

在settings.py中配置:


LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'filters': {
        'special': {
            '()': 'project.logging.SpecialFilter',
            'foo': 'bar',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['special']
        },
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/path/to/django/debug.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'propagate': True,
        },
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
        'myproject.custom': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
            'filters': ['special']
        }
    }
}

该日志配置做了以下事情:


识别配置为 ‘dictConfig 版本 1’ 格式。目前,这是唯一的 dictConfig 格式版本。


定义两个格式化程序:

simple,输出日志级别名称(如 DEBUG)和日志信息。

format 字符串是一个普通的 Python 格式化字符串,它描述了每个日志行要输出的细节。可以输出的完整细节列表可以在 Formatter Objects 中找到。

verbose,输出日志级别名称、日志信息,以及生成日志信息的时间、进程、线程和模块。


定义两个过滤器:

project.logging.SpecialFilter,使用别名 special。如果这个过滤器需要额外的参数,它们可以作为过滤器配置字典中的附加键提供。在这种情况下,当实例化 SpecialFilter 时,参数 foo 将被赋予一个 bar 的值。

django.utils.log.RequireDebugTrue,当 DEBUG 为 True 时,传递记录。


定义两个处理程序:

console,一个 StreamHandler,它将任何 INFO (或更高)消息打印到 sys.stderr。该处理程序使用 simple 输出格式。

mail_admins, an AdminEmailHandler, which emails any ERROR (or higher) message to the site ADMINS. This handler uses the special filter.

‘filename’ 指向的路径改为当前运行 Django 应用的用户可写的路径


配置三个记录器。

django,将所有信息传递给 console 处理程序。

django.request,它将所有 ERROR 消息传递给 mail_admins 处理程序。此外,这个记录器被标记为 不 传播消息。这意味着写给 django.request 的日志信息不会被 django 日志处理程序处理。

myproject.custom,它将所有 INFO 或更高等级的消息传递给两个处理程序——console 和 mail_admins。这意味着所有 INFO 级别(或更高)的消息将被打印到控制台;ERROR 和 CRITICAL 消息也将通过电子邮件输出。


日志配置说明2

在settings.py中配置:


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是日志格式化器,它代表了如何格式化输出日志,其中格式占位符分别表示:


  1. %(name)s - 记录器的名称
  2. %(levelno)s - 数字形式的日志记录级别
  3. %(levelname)s - 日志记录级别的文本名称
  4. %(filename)s - 执行日志记录调用的源文件的文件名称
  5. %(pathname)s - 执行日志记录调用的源文件的路径名称
  6. %(funcName)s - 执行日志记录调用的函数名称
  7. %(module)s - 执行日志记录调用的模块名称
  8. %(lineno)s - 执行日志记录调用的行号
  9. %(created)s - 执行日志记录的时间
  10. %(asctime)s - 日期和时间
  11. %(msecs)s - 毫秒部分
  12. %(thread)d - 线程ID(整数)
  13. %(threadName)s - 线程名称
  14. %(process)d - 进程ID (整数)


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


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


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


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


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


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


配置Django-Debug-Toolbar


参考:

https://github.com/jazzband/django-debug-toolbar

https://blog.csdn.net/cn_1937/article/details/82715983

Django-Debug-Toolbar是项目开发阶段辅助调试和优化的必备工具,只要配置了它,就可以很方便的查看到如下表所示的项目运行信息,这些信息对调试项目和优化Web应用性能都是至关重要的。


项目 说明
Versions Django的版本
Time 显示视图耗费的时间
Settings 配置文件中设置的值
Headers HTTP请求头和响应头的信息
Request 和请求相关的各种变量及其信息
StaticFiles 静态文件加载情况
Templates 模板的相关信息
Cache 缓存的使用情况
Signals Django内置的信号信息
Logging 被记录的日志信息
SQL 向数据库发送的SQL语句及其执行时间


配置方法

  1. 安装Django-Debug-Toolbar。
 pip install django-debug-toolbar
  1. 配置 - 修改settings.py。
if DEBUG:
    MIDDLEWARE += [
        'debug_toolbar.middleware.DebugToolbarMiddleware',
    ]
    INSTALLED_APPS += [
        'debug_toolbar',
    ]
    INTERNAL_IPS = ['127.0.0.1', ]
    # this is the main reason for not showing up the toolbar
    import mimetypes
    mimetypes.add_type("application/javascript", ".js", True)
    DEBUG_TOOLBAR_CONFIG = {
        # 'INTERCEPT_REDIRECTS': False,
        # 引入jQuery库 如果项目组包含jquery,这里可以为 ""
        'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
        # 工具栏是否折叠
        'SHOW_COLLAPSED': True,
        # 是否显示工具栏
        'SHOW_TOOLBAR_CALLBACK': lambda x: True,
    }
  1. 配置 - 修改urls.py。
# 在urls.py文件最后面添加
from django.conf import settings
if settings.DEBUG:
    import debug_toolbar
    urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))

4.在配置好Django-Debug-Toolbar之后,页面右侧会看到一个调试工具栏,如下图所示,上面包括了如前所述的各种调试信息,包括执行时间、项目设置、请求、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。

9d5592bf1aae64fce8adbfd74aba76ee_149b3f0cfd074b678e306beb2a08c213.png

优化ORM-excel导出函数export_teachers_excel(request):

在配置了日志或Django-Debug-Toolbar之后,我们可以查看一下之前将老师数据导出成Excel报表的视图函数执行情况,这里我们关注的是ORM框架生成的SQL查询到底是什么样子的,


0959e83958f01b5c7542073db097e0e9_6484298e766e4309b1e3c3dea9b2e4d4.png

相信这里的结果会让你感到有一些意外。执行Teacher.objects.all()之后我们可以注意到,在控制台看到的或者通过Django-Debug-Toolbar输出的SQL是下面这样的:

fd461faa022a92601706fef8e02f68e6_e4a6d0d2e3a246ea8f58f72c86ff4c5e.png


这里的问题通常被称为“1+N查询”(有的地方也将其称之为“N+1查询”),原本获取老师的数据只需要一条SQL,但是由于老师关联了学科,当我们查询到N条老师的数据时,Django的ORM框架又向数据库发出了N条SQL去查询老师所属学科的信息。

在一条SQL中可以基于连接查询完成老师和学科的查询。

在使用Django的ORM框架时可以基于如下方法:


对于多对一关联(如投票应用中的老师和学科),我们可以使用QuerySet的用select_related()方法来加载关联对象;

而对于多对多关联(如电商网站中的订单和商品),我们可以使用prefetch_related()方法来加载关联对象。


在导出老师Excel报表的视图函数

def export_teachers_excel(request):

中,我们可以按照下面的方式优化代码。

    # 查询所有老师的信息
    # queryset = Teacher.objects.all() # 注释掉这句话,
    queryset = Teacher.objects.all().select_related('subject') # 修改为这句话

优化ORM-excel生成报表函数def get_teachers_data(request):

事实上,用ECharts生成前端报表的视图函数中,查询老师好评和差评数据的操作也能够优化,因为在这个例子中,我们只需要获取老师的姓名、好评数和差评数这三项数据,但是在默认的情况生成的SQL会查询老师表的所有字段。可以用QuerySet的only()方法来指定需要查询的属性,也可以用QuerySet的defer()方法来指定暂时不需要查询的属性,这样生成的SQL会通过投影操作来指定需要查询的列,从而改善查询性能,

函数中:def get_teachers_data(request):

代码如下所示:


# queryset = Teacher.objects.all()
queryset = Teacher.objects.all().only('name', 'good_count', 'bad_count')

当然,如果要统计出每个学科的老师好评和差评的平均数,利用Django的ORM框架也能够做到,代码如下所示:


queryset = Teacher.objects.values('subject').annotate(good=Avg('good_count'), bad=Avg('bad_count'))

这里获得的QuerySet中的元素是字典对象,每个字典中有三组键值对,分别是代表学科编号的subject、代表好评数的good和代表差评数的bad。如果想要获得学科的名称而不是编号,可以按照如下所示的方式调整代码:


queryset = Teacher.objects.values('subject__name').annotate(good=Avg('good_count'), bad=Avg('bad_count'))

可见,Django的ORM框架允许我们用面向对象的方式完成关系数据库中的分组和聚合查询。


总结


本文主要是Django系列博客。本文是Django日志配置与Django-Debug-Toolbar配置。

日志配置:


1.配置settings.py中的LOGGING


Django-Debug-Toolbar配置:


1.安装依赖库

2.修改settings.py文件

3.修改urls.py文件

4.测试运行

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
监控 Serverless 数据库
Serverless 应用引擎常见问题之biphon-education-配置了SLS后一直重启如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
28 5
|
1月前
|
存储 JSON 监控
可以通过配置Filebeat来将Higress日志持久化到磁盘
【2月更文挑战第10天】可以通过配置Filebeat来将Higress日志持久化到磁盘
29 4
|
2月前
|
Java
flume的log4j.properties配置说明
flume的log4j.properties配置说明
|
2月前
|
Java 计算机视觉 Python
我的自描外挂制作日志——FPS类游戏的自瞄【优化改进1】
我的自描外挂制作日志——FPS类游戏的自瞄【优化改进1】
37 1
|
5天前
|
Java
log4j异常日志过滤规则配置
log4j异常日志过滤规则配置
15 0
|
10天前
|
Python
Django开发——配置环境
Django开发——配置环境
|
12天前
|
测试技术 持续交付 Docker
Django中的自动化部署与持续集成实践
【4月更文挑战第15天】本文介绍了Django项目中自动化部署与持续集成的实践方法。自动化部署通过选择Ansible、Fabric或Docker等工具,编写部署脚本,配置持续集成工具(如Jenkins、GitLab CI),确保服务器环境一致,实现快速应用上线。持续集成则涉及配置版本控制系统,设置自动化构建和测试,编写全面的测试用例,集成代码质量检查工具,并配置通知机制,以提升代码质量和开发效率。这两者结合能有效提升项目的迭代速度和可靠性。
|
18天前
|
JavaScript 中间件 Python
Django如何配置解决CORS问题
Django如何配置解决CORS问题
17 0
|
1月前
|
SQL JSON Kubernetes
Seata常见问题之服务端 error日志没有输出,客户端执行sql报错如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
107 0
|
1月前
|
前端开发 开发工具 iOS开发
mPaaS常见问题之真机预览与调试扫码调式 release包开启日志如何解决
mPaaS(移动平台即服务,Mobile Platform as a Service)是阿里巴巴集团提供的一套移动开发解决方案,它包含了一系列移动开发、测试、监控和运营的工具和服务。以下是mPaaS常见问题的汇总,旨在帮助开发者和企业用户解决在使用mPaaS产品过程中遇到的各种挑战
23 0