首页 > 编程 > Python > 正文

Django中间件工作流程及写法实例代码

2020-02-22 23:08:08
字体:
来源:转载
供稿:网友

熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截。

django中的中间件(middleware)就是类似钩子的一种存在。下面我们来介绍一下,并且给出一些实例。

1、Middleware的工作流程

我盗了一个图,看网上很多人用这个图,来源已经追不明白了。简单声明一下,这个图不是我的。看着图我们分析一下:

1)django的请求相应流程:HttpRequest -> RequestMiddleware -> view function -> ResponseMiddleware -> HttpResponse

可以看到一个请求到响应的过程,中间夹着两个middleware流程,请求中间件和响应中间件。

也就是说,django提供了一种机制,在:

    请求到达视图函数中间 视图函数到响应之间

支持嵌入钩子。

这种钩子的特点:

    全局,一旦你使用了中间件,并且发布生效的话,所有的请求都会经过你嵌入的中间件。 性能敏感,如果你的中间件性能差的话,那么会影响服务的整体性能。

2) django的middleware包含四个钩子函数:process_request/process_view/process_response/process_exception

process_request:接受request之后确定所执行的view之前

process_view:确定了所要执行的view之后,view真正执行之前

process_response:view执行之后

process_exceptionview:view执行抛出异常

而插入middleware的过程是在settings.py中配置,如下默认配置,我只截取了两个中间件:SessionMiddleware和CommonMiddleware。

MIDDLEWARE_CLASSES = (  'django.contrib.sessions.middleware.SessionMiddleware',  'django.middleware.common.CommonMiddleware',    ...    )

我们简单看一下SessionMiddleware的实现

import timefrom importlib import import_modulefrom django.conf import settingsfrom django.utils.cache import patch_vary_headersfrom django.utils.http import cookie_dateclass SessionMiddleware(object):  def __init__(self):    engine = import_module(settings.SESSION_ENGINE)    self.SessionStore = engine.SessionStore  def process_request(self, request):    session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)    request.session = self.SessionStore(session_key)  def process_response(self, request, response):    """    If request.session was modified, or if the configuration is to save the    session every time, save the changes and set a session cookie or delete    the session cookie if the session has been emptied.    """    try:      accessed = request.session.accessed      modified = request.session.modified      empty = request.session.is_empty()    except AttributeError:      pass    else:      # First check if we need to delete this cookie.      # The session should be deleted only if the session is entirely empty      if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:        response.delete_cookie(settings.SESSION_COOKIE_NAME)      else:        if accessed:          patch_vary_headers(response, ('Cookie',))        if modified or settings.SESSION_SAVE_EVERY_REQUEST:          if request.session.get_expire_at_browser_close():            max_age = None            expires = None          else:            max_age = request.session.get_expiry_age()            expires_time = time.time() + max_age            expires = cookie_date(expires_time)          # Save the session data and refresh the client cookie.          # Skip session save for 500 responses, refs #3881.          if response.status_code != 500:            request.session.save()            response.set_cookie(settings.SESSION_COOKIE_NAME,                request.session.session_key, max_age=max_age,                expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,                path=settings.SESSION_COOKIE_PATH,                secure=settings.SESSION_COOKIE_SECURE or None,                httponly=settings.SESSION_COOKIE_HTTPONLY or None)    return response            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表