如何編寫自定義 django 中間件

django 中間件

中間件是 Django 請求/響應處理的鉤子框架。它是一個輕量級的、低級的“插件”系統,用於全局改變 Django 的輸入或輸出。

  • call(self, request), response = self.get_response(request)獲得的是此次要響應給客戶端的響應,前後的代碼,在客戶端,發起請求後,接收到響應前各執行一次。
  1. 在 response = self.get_response(request)之前的代碼段將在客戶端,發起請求後,路由匹配前執行。
  2. 在response = self.get_response(request)之後的代碼段將在向客戶端響應請求前執行
  • process_view(request, view_func, *view_args, **view_kwargs),在url匹配後視圖函數處理前調用,如果return None, 那麼,調用完後執行url匹配後的視圖函數
  • def process_exception(request, exception, *args),視圖函數執行失敗執行此函數

創建工程和應用

在 frequencylimit / frequencylimitmiddleware.py 下編寫中間件類

from django.http import HttpResponse

# Create your views here.

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.
        print("中間件初始化,__init__")

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        print("經過下一個中間件之前,__call__")

        # 獲得 process_view 返回的response 或 視圖返回response
        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.
        print("request.META['REMOTE_ADDR']", request.META["REMOTE_ADDR"])

        print("訪問完視圖,__call__")
        # print(response.__dict__)
        # content = response.__dict__['_container'][0].decode(encoding="utf8")
        # print("content:",content)
        return response

    # 如果return None,就訪問視圖 view_func(請求對應的後臺處理程序)
    # 如果return HttpResope對象,那麼就不會執行後臺相應的程序
    def process_view(request, view_func, *view_args, **view_kwargs):
        print("訪問視圖前:process_view")
        # return HttpResponse("你還沒訪問到視圖") 

    def process_exception(request, exception, *args):
        print("服務器出錯了....",*args)
        return HttpResponse("服務器出錯了....%")

在index / view.py 編寫視圖

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
def index(request):
    print("執行 index_views")
    raise KeyError
    return render(request, "index.html", {"content": "ok"})

配置路由

from django.contrib import admin
from django.urls import path

from index.views import index

urlpatterns = [
    path('admin/', admin.site.urls),
    path("index/", index),
]

設置 settings

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 註冊應用
    'index',
    'frequencylimit',
]

MIDDLEWARE = [
	# 自定義的中間件
	# 放在最上面,客戶端的訪問requst,按順序從前往後經過中件間的檢查,最後訪問後臺得到response,
	# reponse按順序從後往前過中件間的審視最後響應給客戶端
    "frequencylimit.frequencylimitmiddleware.SimpleMiddleware",
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

執行結果

System check identified no issues (0 silenced).
March 07, 2019 - 10:22:17
Django version 2.1.7, using settings 'webSite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
中間件初始化,__init__
經過下一個中間件之前,__call__
訪問視圖前:process_view
執行 index_views
服務器出錯了....
訪問完視圖,__call__
[07/Mar/2019 10:22:24] "GET /index/ HTTP/1.1" 200 23

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章