Django中间件
- 概念:Django中一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。无侵入的开发方式,增强了Django框架的健壮性。
Django内置的六个中间件方法
- 类似于Flask框架的请求钩子
1. 初始化
-
无需要任何参数、服务器响应第一次请求的只调用一次
def __init__(): pass
2. 处理请求前
-
在每个请求上调用,返回None 或 HttpResponse,需要接受请求对象
def process_request(request): pass # 返回None / HttpResponse继续往下传递 return None/HttpResponse
3.处理视图前
在每个请求上调用, 返回None 或者 HttpResponse。
-
接收请求参数:请求对象、请求的视图函数、请求视图参数
def process_view(request, view_func, view_args, view_kwargs): pass return HttpResponse
4.处理模版响应前
在每个请求上调用,返回实现了的render 方法的响应对象。
-
请求参数:请求对象、响应对象
def process_templates_response(request, response): pass return
5.处理响应后
所有的响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse
-
请求参数:请求对象、响应对象
def process_response(request, response): pass return HttpResponse
6.异常处理
当视图中抛出异常时候调用,在每个请求视图上调用,返回一个HttpResponse对象
-
请求参数:请求对象、抛出异常
def process_response(request, exception): pass return HttpResponse
自定中间件的定义方法
1.自定义
定义一个中间件工厂函数、然后返回一个可以别出调用的中间件
中间件工厂函数需要接受一个可以调用的get_response对象
-
返回的中间件也是一个可以调用的对象,并像视图一样需要接受一个request对象参数,返回一个response对象
# 本质:中间件就是一个装饰器,get_response:就是视图函数 def my_middleware(get_response): # 1.仅在Django第一次配置初始化的时候执行一次,在DEBUG模式下会执行两次init print('init') def middleware(request): # 2.每个请求匹配到URL处理视图函数之前被调用 print('before request 被调用前') response = get_response(request) # 3.每个请求处理视图函数之后被调用 print('after request 被调用后') return response return middleware
定义好的中间件需要在settings.py文件中注册
定义多个中间件执行顺序:请求视图前,中间由上至下执行。请求视图后,中间件由下至上执行。
2.使用场景
-
异常处理的方法的重写,因为原有的中间件不能捕获数据库错误
# 添加Django REST framework的默认异常处理方法,redis和mysql异常 from rest_framework.views import exception_handler as drf_exception_handler import logging from django.db import DatabaseError from redis.exceptions import RedisError from rest_framework.response import Response from rest_framework import status # 获取在配置文件中定义的logger,用来记录日志 logger = logging.getLogger('django') def exception_handler(exc, context): """ 自定义异常处理 :param exc: 异常 :param context: 抛出异常的上下文 :return: Response响应对象 """ # 调用drf框架原生的异常处理方法 response = drf_exception_handler(exc, context) if response is None: view = context['view'] if isinstance(exc, DatabaseError) or isinstance(exc, RedisError): # 数据库异常 logger.error('[%s] %s' % (view, exc)) response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response
Flask 请求钩子
1. 概念
- 在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如
- 在请求开始时,建立数据库连接;
- 在请求开始时,根据需求进行权限校验;
- 在请求结束时,指定数据的交互格式;
- 为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设施的功能,即请求钩子。
- 请求钩子是通过装饰器的形式实现
2. Flask四种请求钩子
-
before_first_request
# 在第一次请求之前会调用(在发起请求之前就执行该请求钩子) # 应用地方:程序的初始化操作(一些准备工作,数据的链接请求或扫尾工作) @app.before_first_request def before_first_request(): print('before_first_request')
-
before_request
# 在每一次请求之前会调用 # 应用:用户的权限验证 @app.before_request def before_request(): # 在这里可以做一些判断,这里使用return 后面的都不会执行(视图函数都不会进入) print('before_request') # if .... # return 'hehe' # return判断以后,后面的接口就不会进入,做用户的黑名单校验
-
after_request
# 在每次请求执行之后执行 @app.after_request def after_request(response): print('after_request') # 这里可以对响应对象做处理--->一般都是对响应做处理 # 对所有返回的json数据进行处理(所有的都处理掉) response.headers["Content-Type"] = "application/json" return response
-
teardown_request
# 在每次请求执行的最后执行,如果服务器出现错误,这里也可以获取 @app.teardown_request # @app.errorhandler def teardown_request(error): # 可以记录错误 # 以后可能会用到请求数据库的自动提交 print('teardown_request:%s' % error)
Spider中间件
1. 爬虫中间件
-
当爬虫创建时回调
@classmethod def from_crawler(cls, crawler): """当爬虫被创建是回调""" # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s
-
进入爬虫回调函数
def process_spider_input(self, response, spider): """ 1。响应对象 进入 爬虫时 回调 2。返回None 或者 抛出异常--》None时继续往下执行 """ # Called for each response that goes through the spider # middleware and into the spider. # Should return None or raise an exception. return None
-
爬虫返回数据到引擎回调
def process_spider_output(self, response, result, spider): """ 当爬虫 返回 数据给引擎的时候 回调 Request, dict or Item objects :return:必须返回 请求对象, 字典对象, item数据模型对象 """ # Called with the results returned from the Spider, after # it has processed the response. # Must return an iterable of Request, dict or Item objects. for i in result: yield i
-
处理引擎首次获取start_url 构建 request 对象回调
def process_start_requests(self, start_requests, spider): """处理引擎首次 获取 start_url构建 request 对象时 回调""" # 也要经过爬虫中间件 # Called with the start requests of the spider, and works # similarly to the process_spider_output() method, except # that it doesn’t have a response associated. # Must return only requests (not items). for r in start_requests: yield r
2. 下载中间件
-
spider创建 初始化
@classmethod def from_crawler(cls, crawler): """当spider 被创建时,回调此方法,一般初始化方法""" # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s
-
引擎把请求 request 对象传递给下载器请求
def process_request(self, request, spider): """ 当引擎把请求 request 传递给 下载器时候回调 返回: None:继续处理请求 Response:把响应对象还给引擎,并且引擎会把数据传递给爬虫 Request:把请求对象还给引擎, 引擎会重新放入请求调度器队列中 raise IgnoreRequest:触发异常处理,会回调函数process_exception来处理异常 """ # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None
-
下载器,完成请求返回引擎响应对象
def process_response(self, request, response, spider): """当下载器完成,返回给引擎响应对象时 回调 返回: Response:把响应对象还给引擎,并且引擎会把数据传递给爬虫 Request:把请求对象还给引擎, 引擎会重新放入请求调度器队列中, 继续发起请求 """ # Called with the response returned from the downloader. # Must either; # - return a Response object # - return a Request object # - or raise IgnoreRequest return response
-
处理异常
def process_exception(self, request, exception, spider): """处理异常函数 None:继续处理这个异常,向下一个中间件处理异常 Response:停止异常传递 Request:停止异常传递""" # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass