天天看點

如何編寫自定義 django 中間件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),視圖函數執行失敗執行此函數

建立工程和應用

  • django-admin startproject mySite
  • python manage.py startapp frequencylimit
  • python mange.py startapp index
  • 在 frequencylimit 下建立 frequencylimitmiddleware.py

在 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
           
如何編寫自定義 django 中間件django 中間件