django middelware

django中间件是用来处理request和respone的钩子,通过中间件可以控制request的数据和response的响应。内置的middelware有 cache\common\Exception\Gzip\ConditionalGet\Locale\Message\Security等等。

创建自己的Middleware

middleware是一个可被调用的函数,接受一个get_response参数。middleware有两种形式

  1. 函数式middleware

    1
    2
    3
    4
    5
    6
    7
    8
    def simple_middleware(get_response):
    # One-time configuration and initialization.
    def middleware(request):
    # Code to be executed for each request before # the view (and later middleware) are called.
    response = get_response(request)
    # Code to be executed for each request/response after # the view is called.
    return response
    return middleware
  2. 类式middelware

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class SimpleMiddleware(object):
    def __init__(self, get_response):
    self.get_response = get_response
    # One-time configuration and initialization.
    def __call__(self, request):
    # Code to be executed for each request before # the view (and later middleware) are called.
    response = self.get_response(request)
    # Code to be executed for each request/response after # the view is called.
    return response

对于1.9版本之前的,需要写成get_response=None的形式,因为之前的老版本不接受任何参数。
老版本的middleware在setting中的定义是MIDDLEWARE_CLASS,新版本的为MIDDLEWARE.

下面用一张图阐释一下middleware的作用:

Demo

接下来创建一个Middleware将django运行中的错误自动去stackoverflow.com查询答案。
运行效果如图:

创建Middleware类

1
2
3
4
5
6
7
8
9
class StackOverflowMiddleware(object):
def __init__(self,get_response=None):
self.get_response=get_response
def __call__(self,request):
return self.get_response(request)
def process_exception(self, request, exception):
return None

initcall在新版中必须要写,而旧版本不用。因为新版本的Middleware的原理是洋葱式的传递,由外向内,response则是由内向外,层层传递。

在setting中添加Middleware

1
2
3
4
5
6
7
8
9
10
11
12
MIDDLEWARE = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'soet.middleware.StackOverflowMiddleware',
)

旧版本相应的为MIDDLEWARE_CLASS

调用stackoverflow API完成查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import requests
from django.conf import settings
class StackOverflowMiddleware(object):
def process_exception(self, request, exception):
if settings.DEBUG:
intitle = u'{}: {}'.format(exception.__class__.__name__, exception.message)
print intitle
url = 'https://api.stackexchange.com/2.2/search'
headers = { 'User-Agent': 'github.com/vitorfs/seot' }
params = {
'order': 'desc',
'sort': 'votes',
'site': 'stackoverflow',
'pagesize': 3,
'tagged': 'python;django',
'intitle': intitle
}
r = requests.get(url, params=params, headers=headers)
questions = r.json()
print ''
for question in questions['items']:
print question['title']
print question['link']
print ''
return None