Task8 Django的日志
Django的日志Logging的组成成分:
- 日志的版本号 version
- 日志的格式化 formatters
- 日志的处理器 handlers
- 日志的记录器 loggers , 默认存在"django", “django request”
- 日志的过滤器 filters
其实这一章我听得也是比较模糊的,不过这个应该算是Django的核心配置之一,所以放大佬的链接镇楼:https://zhuanlan.zhihu.com/p/133864368。
好吧,我疯狂恶补了一下日志 (暴露了我之前写项目从来没有日志只靠编译器给BUG的过程呜呜呜)。其实Django的日志并不是Django中自定义或者新加的部分,而是Python的基础包logging就提供的东西:python logging - 刘江的python教程 (liujiangblog.com)不过Django支持在setting中进行配置的过程,东西也比较简单详见上面的链接,我普普通通的来一个例子(没涉及到中间件,勿喷)
LOGGING = {
# 版本,这个随便写就行,最好写1.0嘛
'version': 1.0,
# 日志的格式
'formatters': {
# 这个格式的名字可以自定义的,自定义后的名字会在下面的模块用到
'model': {
# 格式具体的样子, 包括时间,等级都可以配置
'format': '{"time": "%(asctime)s", "level": "%(levelname)s", "name": "%(name)s" }',
# 时间的格式
'datefmt': '%Y-%m-%d %H:%M:%S'
}
},
# 处理器,可以包括流输出, IO写入等
'handlers': {
# 又到了喜闻乐见的自定义名字环节,以下是输出处理器,文件处理器
'flush':{
'class':'logging.StreamHandler',
'level': INFO,
'formatter': 'model'
},
'file':{
'class':'logging.FileHandler'
'level': 'WARNING',
'formatter': 'model',
'filename': '文件路径'
}
},
# 记录器
'loggers': {
# 默认叫做django
'django': {
'handlers': ['flush','file'],
'level': 'INFO',
# 一个传播特性,具体请翻博客
'propagate': False
}
}
}
日志的输出就会变成这个样子:
{"time": "2022-03-23 14:26:35", "level": "WARNING", "name": "django.request" }
Task9 Django Cache 文件缓存
话不多说,官方永远的神,链接如下Django 缓存框架 | Django 文档 | Django (djangoproject.com)。 好的官方文档(相当)粗略的看一下之后相信大多数人和我一样是一个比较懵比的状态,主要是在setting的CACHE下面的Location要么是Linux要那么是共享Cache的IP, 好像和我windows没啥关系了。。。不过后面有Redis的时候我感觉我又行了,吧Location直接配到我的Redis上应该会很爽
# 这里是CACHE在Windows上的两种配置方法,一种是配置到文件上,一种是配置到内存中 settings.py
CACHES = {
# 存在文件中
'file':{
'BACKEND':'django.core.cache.bankends.filebased.FileBasedCache'
'Location': '文件地址'
}
# 存在内存中
'memory':{
'BACKEND':'django.core.cache.bankends.locmem.LocmemCache'
#
'Location': 'unquie-snowflake'
}
}
我的一个简单配置,具体参数可以翻Base.py的源码 django.core.cache.backends.base 淡然,你也可以在上面的官方文档继续下拉获取相应的信息。
CACHES = {
# 默认缓存
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'timeout': 300,
'TIMEOUT': 300,
'Location': 'unique-snowflake',
'OPTIONS': {
'CULL_FREQUENCY': 4,
"MAX_ENTRIES": 100,
}
},
}
当我们配置好缓存之后就可以使用了。根据官方文档,我们需要在中间件中加上缓存相关,就可以使用缓存相关的用法了
关于缓存的用法,Django.core.cache提供了一些原生的缓存用法:(按照这个样子看缓存有点像字典啊, 啊本身也接近Redis) eg. 一个Demo:
# 这个语法本身接近原生的Redis,
from django.core.cache import cache
cache.set('name','hello')
cache.get('name')
hello
当然,缓存也可以用@cache_page装饰器来使用,具体使用网上的教程还是很普遍的。我们直接冲redis. 因为我看的教程用的版本有点老了,关于Redis的参数可以借鉴官方,也可以直接看源码。源码上,RedisCache是BaseCache的一个子类,那么,,,该配置的差不多,我们看看redis特有的配置参数
'db': 使用的数据库名称
'parser_class': 'redis.connect.PythonParser'
'pool_class' : 'redis.BlockingConnectionPool'(最大连接数是50,超时时间是20s)
关于Redis 的cache命令已经和原汁原味的Redis方Python调用Redis已经差不多了,我们实操
# Redis cache配置
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://192.168.75.140:6379',
'TIMEOUT': 300,
'OPTIONS':{
'db': '8',
'parser_class': 'redis.connection.PythonParser',
'pool_class': 'redis.BlockingConnectionPool',
}
}
# cahce传输
cache.add('bsauycfv','UGDCIKYqf')
添加成功(但是不知道为什么响应有点慢啊)
缓存信息,最广泛的应用的就是Session了,用来存储一些登录的信息啦。Session可以在我们的setting中配置一下,
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_COOKIE_NAME = 'session_id'
# 存在时间,默认为两周,我改成了一小时,传参为数字型,单位s
SESSION_COOKIE_AGE = 3600
# Session使用cache的别名应该,源代码是这么写的 self._cache = caches[settings.SESSION_CACHE_ALIAS]。
SESSION_COOKIE_ALIAS = 'default'
之后我们重新在登陆界面加上session, 在Redis缓存中就会看到
request.session['welcome'] = {
'name':'hellos'
}
在1:django.contrib.sessions.cache+cacheid就能看到我们存储的信息:\x80\x05\x95!\x00\x00\x00\x00\x00\x00\x00}\x94\x8C\x07welcome\x94}\x94\x8C\x04name\x94\x8C\x06hellos\x94ss.(能秒抢认出来我们的信息),而Cookie中只存放了session id , 其他信息并没有存储。
Task10 Django信号机制
要了解Django的信号机制,首先要搞清楚什么是信号。信号是进程与进程之间交流的工具,如当进程协同的通讯。信号(Signal) 是进程之间传递信息的一种方式(显然并不仅存在信号一种方式)。信号可以传递的消息比较简单粗糙,适用于进程中介,终止等。
Django提供“信号调度”机制, 用于监听框架中执行默写擦偶哦,实现业务与模型或师徒之间的解耦。Django 内置了信号模块https://docs.djangoproject.com/zh-hans/4.0/ref/signals/:(下图是一个跟模型操作相关的信号。信号真的超级多我就不列举了去看官方吧)
信号的处理需要在app 的init中定义啦,才能接收到信号,以request为例(还是要多联系哒)日志也可以用信号实现。
__init__.py
# 一定要有sender和kwargs参数
def get_request(sender, **kwargs):
print('Get a request, sender is', sender, type(kwargs))
def finish_request(sender, **kwargs):
print('Finish a request, sender is', sender, type(kwargs))
# 连接信号
request_started.connect(get_request)
request_finished.connect(finish_request)
# kwargs是一个字典 , 可以写成如下形式:
# kwargs = {'signal':signal 对象的__str__, 'environ': META信息}
# 以下是响应
Get a request, sender is <class 'django.core.handlers.wsgi.WSGIHandler'> <class 'dict'>
This is response middleware
[24/Mar/2022 14:15:49] "GET /son1/cvb/ HTTP/1.1" 200 1213
Finish a request, sender is <class 'django.core.handlers.wsgi.WSGIHandler'> <class 'dict'>
当然,信号函数是可以自定义的,其实我们翻源码发现, 这玩应都是dispatch的对象啊兄弟
# django.core.signals
from django.dispatch import Signal
# 这个东西是WSGI调度的时候会在源码发信号由这里接受
request_started = Signal()
request_finished = Signal()
got_request_exception = Signal()
setting_changed = Signal()
那我们可以自定义信号啦:注意,很多教程给的低版本的信号使用providing_args,不过在4.0中已经被取缔了
# 很多教程给的低版本的信号使用providing_args,不过在4.0中已经被取缔了
#声明信号
from django.dispatch import Signal
signal_login = Signal()
# 发送信号,参数自由,但是一定要加sender, 而且sender必须是一个类否则信号不会发出来
from .signal import signal_login
signal_login.send(sender = HttpRequest, name='Laowang', IsSignal=True)
# 接受信号
from .signal import signal_login
def get_login_signal(sender, **kwargs):
print('接收到login的信号 ', sender, kwargs)
signal_login.connect(get_login_signal)
# 输出
接收到login的信号 <class 'django.http.request.HttpRequest'> {'signal': <django.dispatch.dispatcher.Signal object at 0x000001E485CC7F70>, 'name': 'Laowang', 'IsSignal': True}