Django中间件与python日志模块 介绍
一、Django中間件
1.1 介紹
Django中的中間件是一個輕量級、底層的插件系統,介于request與response處理之間的一道處理過程(用來處理特定業務的請求和響應)。中間件的設計為開發者提供了一種無侵入式的開發方式,增強了Django框架的健壯性。
我們可以使用中間件,在Django處理視圖的不同階段對輸入或輸出進行干預。
請求—中間件—響應:
1.1.1 中間件配置
? 定義好中間件后,需要在settings.py 文件中添加注冊中間件
MIDDLEWARE = ['django.middleware.security.SecurityMiddleware', # 安全中間件'django.contrib.sessions.middleware.SessionMiddleware', # 會話中間件'corsheaders.middleware.CorsMiddleware', # 跨域請求中間件'django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware', # 防偽造跨域請求中間件'django.contrib.auth.middleware.AuthenticationMiddleware', # 授權中間件'django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware', ]【拓展】HTTP請求方法:
GET: 查詢
POST: 添加或修改數據
PUT : 修改數據
DELETE: 刪除數據
OPTIONS: 探測服務器是否支持跨域
Access-Control-Allow[-Origin|Headers|Methods|Credentials]
訪問-控制-允許-[源|頭|方法|認證]
1.1.2 中間件的鉤子函數(生命周期):
process_request: 請求到達時,未到路由 process_view: 轉到view處理函數之前 process_exception: 在view處理函數中拋出異常時 process_response: 在View響應之后,向客戶返回(輸出)之前 process_template_response: 響應之前,渲染模板之后1.1.3 自定義中間件類
from django.utils.deprecation import MiddlewareMixinclass AuthUserMiddleware(MiddlewareMixin):def process_request(self, request):passdef process_view(self, request, view, *args, **kwargs):passdef process_exception(self, request, exception):passdef process_response(self, request, response):return response1.1.4 通過中間件實現的功能
- 請求黑名單: 1秒內允許2次請求(正常),非正常,則在process_request()方法直接返回 - 提取授權用戶的信息和權限驗證: 提前配置請求路徑和用戶權限 - 異常的友好提示 - 緩存數據(減少數據庫的交互次數): process_response() 對response對象進行序列化和緩存。 - 記錄日志(logging 模塊)1.2 線程方式實現緩存
import time from django.http import HttpResponse from django.utils.deprecation import MiddlewareMixin import threadingcached = {}# 過期緩存監控的線程 class ExpireThread(threading.Thread):def clear(self, path, max_age):time.sleep(max_age)print('--checked--', path, cached.keys())if path in cached:cached.pop(path)def run(self):while True:time.sleep(1)print('--check--', cached.keys())for path, resp_max_age in cached.items():threading.Thread(target=self.clear,args=(path, resp_max_age[-1])).start()class MyMiddleware(MiddlewareMixin):def process_request(self, request):print('--process_request---', request.path)# 判斷當前請求路徑是否在緩存中# 如果存在則,直接返回響應if request.path in cached:return cached[request.path][0]def process_view(self, request, view, *args, **kwargs):# args 表示 view函數的位置參數# kwargs 表示 view函數的關鍵參數print('---process_view---', args)def process_exception(self, request, exception):print(request.path, dir(exception))print('----process_exception----', exception)return HttpResponse('<h3>Error Page 500: %s</h3>' % str(exception))def process_response(self, request, response):print('---process_response---')if request.path not in cached:# 存入緩存(內存)print('---存入緩存---')cached[request.path] = (response, 3)print('---緩存---', cached)return responseExpireThread().start()注冊中間件, 在settings.py文件中,修改MIDDLEWARE,如下所示:
MIDDLEWARE = [...'apiapp.middleware.MyMiddleware','django.middleware.common.CommonMiddleware',... ]1.3 基于Redis實現緩存頁面
from utils.caches import save_response, get_response, has_response import pickle import base64class RedisCacheMiddleware(MiddlewareMixin):def process_request(self, request):print('--process_request---', request.path)# 判斷當前請求路徑是否在緩存中# 如果存在則,直接返回響應if has_response(request.path):resp_base_str = get_response(request.path)resp_bytes = base64.b32decode(resp_base_str.encode())response = pickle.loads(resp_bytes)return responsedef process_response(self, request, response):print('---process_response---')# 存入緩存(內存)if not has_response(request.path):resp_bytes = pickle.dumps(response) # 將python的任意對象序列化字段碼# b'QABWGZDKMFXGO3ZONB2HI4BOOJSXG4DPNZZWKCSIOR2HAUTFONYG63TTMUFHCABJQFYQC7LRAIUFQCAAAAAF'resp_base64_str = base64.b32encode(resp_bytes).decode()save_response(request.path, resp_base64_str, 3)return response二、日志模塊
Python的日志模塊是: logging
import logging2.1 日志的四大部分
日志是用于記錄(Logger)程序中的一些重要信息的,記錄的信息按等級(Level)交給特定的處理器Handler按一定的格式(Formatter)進行處理(打印、文件保存、上傳網絡和發送郵件等)。
2.1.1 日志記錄器 Logger
- 記錄日志信息的唯一對象, 根據不同的信息等級使用不同的記錄方法
- x.debug() 記錄調試信息,logging.DEBUG (10)
- x.info() 記錄普通信息, logging.INFO (20)
- x.warning() 記錄警告信息, loggin.WARNING (30)
- x.error() 記錄錯誤信息, logging.ERROR (40)
- x.critical() 記錄嚴重錯誤的信息, loggin.CRITICAL (50)
- 創建或獲取記錄器: logging.getLogger(name) 如果name為空,則默認為root。
- 記錄器可以添加處理器和過濾器: x.addHandler(Handler())、 x.addFilter(Filter() )
2.1.2 日志處理器 Handler
作用: 將記錄器記錄的相關日志信息,進行特定業務的處理,如寫入文件的FileHandler、發送郵件的 SMTPHandler、上傳遠程服務器的HTTPHandler等。
【注意】處理器可以設置日志格式化 Formatter: h.setFormatter(Formatter())
- StreamHandler 流處理器, 控制臺打印的
- FileHandler 文件處理器,將日志消息寫入到文件中
- HTTPHandler 網絡處理器,將日志消息上傳到服務器
- SMTPHandler 郵件處理器,將日志消息發送到指定郵件中。
日志記錄器和處理器的關系:
一個記錄器可以添加多個處理器。
logger.addHandler(handler1) logger.addHandler(handler2) logger = logging.getLogger("network") logger.setLevel(logging.INFO) handler1 = StreamHandler() handler1.setLevel(logging.INFO)handler2 = FileHandler("network.log") handler1.setLevel(logging.WARNING)logger.addHandler(handler1) logger.addHandler(handler2)2.1.3 日志格式化 Formatter
作用: 將記錄日志信息進行格式化(可以選擇重要的信息、或者自定義格式的信息)
經典的日志格式:
[ %(asctime)s - %(levelname)s < line %(lineno)s at %(pathname)s > ] %(message)s如果給定的日志格式中變量不能完成業務需求時,可以自定義:
[ %(asctime)s - %(username)s: %(ip)s < %(action)s > ] %(message)s以上username、ip和action都屬于自定義的格式變量,在記錄器記錄信息時指定extra 參數, 它是一個字典類型,key即為擴展的變量名,value即是它的值。
日志的格式:
| %(name)s Name of the logger (logging channel) 記錄器的名稱| %(levelno)s Numeric logging level for the message (DEBUG, INFO,| WARNING, ERROR, CRITICAL) 數字形式的日志記錄級別| %(levelname)s Text logging level for the message ("DEBUG", "INFO",| "WARNING", "ERROR", "CRITICAL") 日志記錄級別的文本名稱| %(pathname)s Full pathname of the source file where the logging| call was issued (if available) 執行日志記錄調用的源文件的路徑名稱| %(filename)s Filename portion of pathname 執行日志記錄調用的源文件的文件名稱| %(module)s Module (name portion of filename) 執行日志記錄調用的模塊名稱| %(lineno)d Source line number where the logging call was issued| (if available) 執行日志記錄調用的行號| %(funcName)s Function name 執行日志記錄調用的函數名稱| %(created)f Time when the LogRecord was created (time.time()| return value) 執行日志記錄的時間| %(asctime)s Textual time when the LogRecord was created 日期和時間| %(msecs)d Millisecond portion of the creation time 毫秒部分| %(relativeCreated)d Time in milliseconds when the LogRecord was created,| relative to the time the logging module was loaded| (typically at application startup time)| %(thread)d Thread ID (if available) 線程ID| %(threadName)s Thread name (if available) 線程名稱| %(process)d Process ID (if available) 進程ID| %(message)s The result of record.getMessage(), computed just as| the record is emitted 記錄的消息2.1.4 日志過濾器 Filter
作用: 過濾一些敏感的記錄日志信息。
2.2 日志的應用
2.2.1 標準使用
#!/usr/bin/python3 import logging from logging import StreamHandler, FileHandler, Formatter, Filterclass MsgFilter(Filter):def filter(self, record): # record記錄對象# print(dir(record)) # 查看記錄器里面的方法return record.msg.find('混沌') == -1logger = logging.getLogger('middleware') # 設置記錄器的信息等級:DEBUG -> INFO -> WARNING -> ERROR -> CRITICAL logger.setLevel(logging.INFO) # 記錄器可以記錄INFO及以上等級信息# 添加日志過濾器 logger.addFilter(MsgFilter())# 創建日志處理器 handler1 = StreamHandler() # 流處理器,標準輸出 handler1.setLevel(logging.INFO) handler1.setFormatter(Formatter(fmt='[ %(asctime)s - %(levelname)s] %(message)s',datefmt='%Y-%m-%d %H:%M:%S' ))# 向記錄器添加處理器 logger.addHandler(handler1)handler2 = FileHandler('error.log', encoding='utf-8') handler2.setLevel(logging.ERROR) handler2.setFormatter(Formatter(fmt="[ %(asctime)s - %(levelname)s < line %(lineno)s at %(pathname)s > ] %(message)s",datefmt='%Y-%m-%d %H:%M:%S' )) logger.addHandler(handler2)if __name__ == '__main__':# x = logging.getLogger('middleware') # 獲取middleware的記錄器logging.getLogger('middleware').debug('中午吃拉面')logging.getLogger('middleware').info('中午吃木桶飯')logging.getLogger('middleware').warning('中午吃涼皮')logging.getLogger('middleware').error('中午吃粥和夾饃')logging.getLogger('middleware').critical('下午吃混沌')2.2.2 擴展格式化的使用
mylogger = logging.getLogger('sys_action') mylogger.setLevel(logging.INFO)myhandler = StreamHandler() myhandler.setLevel(logging.INFO) myhandler.setFormatter(Formatter(fmt="[ %(asctime)s - %(username)s: %(ip)s < %(action)s > ] %(message)s",datefmt='%Y-%m-%d %H:%M:%S' ))mylogger.addHandler(myhandler)if __name__ == '__main__':extra_info = {'username': 'admin','ip': '10.36.172.110','action': 'del category'}logging.getLogger('sys_action').debug('中午吃拉面', extra=extra_info)logging.getLogger('sys_action').info('中午吃木桶飯', extra=extra_info)logging.getLogger('sys_action').warning('中午吃涼皮',extra=extra_info)logging.getLogger('sys_action').error('中午吃粥和夾饃', extra=extra_info)logging.getLogger('sys_action').critical('下午吃混沌', extra=extra_info)總結
以上是生活随笔為你收集整理的Django中间件与python日志模块 介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从attention到Transform
- 下一篇: python实现Trie 树+朴素匹配字