上下文處理器及中間件

上下文處理器html

  返回一些數據,在全局模板中均可以使用。如登陸後的用戶信息,在不少頁面中都須要使用,可將其放在上下文處理器中,避免在每一個視圖函數中重複返回這個對象。python

在 settings.TEMPLATES.OPTIONS.context_processors 中各個處理器的做用:正則表達式

  • django.template.context_processors.debug:增長一個debug和sql_queries變量。在模板中能夠經過他來查看到一些數據庫查詢。
  • django.template.context_processors.request:增長一個request變量。這個request變量也就是在視圖函數的第一個參數。
  • django.contrib.auth.context_processors.auth:Django有內置的用戶系統,這個上下文處理器會增長一個user對象。
  • django.contrib.messages.context_processors.messages:增長一個messages變量。
  • django.template.context_processors.media:在模板中能夠讀取 MEDIA_URL 。好比想要在模板中使用上傳的文件,那麼這時候就須要使用settings.py中設置的 MEDIA_URL 來拼接url。示例代碼以下: <img src="" /> 
  • django.template.context_processors.static:在模板中可使用STATIC_URL。
  • django.template.context_processors.csrf:在模板中可使用 csrf_token 變量來生成一個 csrf token 。

 

 messages 處理器:sql

 1 # forms.py
 2 # 上下文處理器messages,來爲模板渲染出錯誤信息,如登陸時提示的‘用戶或密碼錯誤’。可定義級別
 3 class Get_error(forms.ModelForm):
 4     def get_error(self):
 5         new_errors = []
 6         errors = self.errors.get_json_data()
 7         for messages in errors.values():
 8             for message_dict in messages:
 9                 for key,message in message_dict.items():
10                     if key == 'message':
11                         new_errors.append(message)
12         return new_errors
13 
14 class SigninForm(Get_error):
15     --snip--
 1 # views.py
 2 # 登陸頁面
 3 class SigninView(View):
 4     def get(self,request):
 5         return render(request,'signin.html')
 6 
 7     def post(self,request):
 8         form = SigninForm(request.POST)
 9         if form.is_valid():
10             username = form.cleaned_data.get('username')
11             password = form.cleaned_data.get('password')
12             # 驗證經過時,保存session信息;將存入數據庫的user.id等於session中的user_id的值。
13             user = User.objects.filter(username=username,password=password).first()
14             if user:
15                 request.session['user_id'] = user.id
16                 return redirect(reverse('index'))
17             else:
18                 print('用戶名或密碼錯誤')
19                 # 設置信息的等級及提醒的內容
20                 # messages.add_message(request,messages.INFO,'用戶名或密碼錯誤!')
21                 messages.info(request,"用戶名或密碼錯誤!")
22                 return redirect(reverse('signin'))
23         else:
24             # errors = form.errors.get_json_data()
25             errors = form.get_error()
26             for error in errors:
27                 messages.info(request,error)
28             print(form.get_error())
29             return redirect((reverse('signin')))

HTML模板:數據庫

 1 <!--signin.html登陸模板-->
 2 <!--snip-->
 3 <td>
 4     <!--渲染出錯信息,級別爲‘info’時顯示紅色-->
 5     {% for message in messages %}
 6          {% if message.tags == 'info' %}
 7              <li style="color: red">{{ message }}</li>
 8          {% endif %}
 9     {% endfor %}
10 </td>

 

 

 

自定義上下文處理器django

  根據這個上下文處理器是屬於哪一個app,而後在這個app中建立一個文件專門用來存儲上下文處理器。好比 context_processors.py 。或者是你也能夠專門建立一個Python包,用來存儲全部的上下文處理器。
  上下文處理器文件中,定義一個函數,這個函數只有一個 request 參數。這個函數中處理完本身的邏輯後,把須要返回給模板的數據,經過字典的形式返回。若是不須要返回任何數據,那麼也必須返回一個空的字典。json

添加處理器:瀏覽器

 1 # settings.py
 2 TEMPLATES = [
 3     {
 4         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 5         'DIRS': [os.path.join(BASE_DIR, 'templates')],
 6         'APP_DIRS': True,
 7         'OPTIONS': {
 8             'context_processors': [
 9                 'django.template.context_processors.debug',
10                 'django.template.context_processors.request',
11                 'django.contrib.auth.context_processors.auth',
12                 'django.contrib.messages.context_processors.messages',
13                 # 添加上下文處理器;
14                 'front.context_processors.front_user'
15             ],
16         },
17     },
18 ]

判斷是否有用戶數據存在:緩存

 1 # context_processors.py
 2 from .models import User
 3 
 4 def front_user(request):
 5     user_id = request.session.get('user_id')
 6     context = {}
 7     if user_id:
 8         try:
 9             user = User.objects.get(pk=user_id)
10             context['front_user'] = user
11         except:
12             pass
13     return context

HTML模板:安全

1 <!--base.html主模板-->>
2 <!--snip-->
3 <!--判斷該網站是否已存在登陸的帳戶,存在時再也不顯示登陸頁面-->
4 {% if front_user %}
5     <li><a href="">{{ front_user.username }}</a></li>
6 {% else %}
7     <li><a href="{% url 'signin' %}">登陸</a></li>
8     <li><a href="{% url 'signup' %}">註冊</a></li>
9 {% endif %}

 

 

中間件

  是在 request 和 response 處理過程當中的一個插件。好比在request到達視圖函數以前,可使用中間件來作一些相關的事情,好比能夠判斷當前這個用戶有沒有登陸,若是登陸了,就綁定一個user對象到request上。也能夠在response到達瀏覽器以前,作一些相關的處理,好比想要統一在response上設置一些cookie信息等。

Django內置的中間件

  1. django.middleware.common.CommonMiddleware:通用中間件。做用:
    • 限制 settings.DISALLOWED_USER_AGENTS 中指定的請求頭來訪問本網站。DISALLOWED_USER_AGENT是一個正則表達式的列表。
      1 # 限制某些網站的訪問
      2 import re
      3 DISALLOWED_USER_AGENTS = [
      4     re.compile(r'^\s$|^$'),         # 含空白符或空白無內容
      5     re.compile(r'.*PhantomJS.*')    # 含有該單詞的
      6 ]
    • 若是開發者在定義url的時候,最後有一個斜槓。可是用戶在訪問url的時候沒有提交這個斜槓,那麼CommonMiddleware會自動的重定向到加了斜槓的url上去。
  2. django.middleware.gzip.GZipMiddleware:將響應數據進行壓縮。若是內容長度少於200個長度,那麼就不會壓縮。
  3. django.contrib.messages.middleware.MessageMiddleware:消息處理相關的中間件。
  4. django.middleware.security.SecurityMiddleware:作了一些安全處理的中間件。好比設置XSS防護的請求頭,好比作了http協議轉https協議的工做等。
  5. django.contrib.sessions.middleware.SessionMiddleware:session中間件。會給request添加一個處理好的session對象。
  6. django.contrib.auth.middleware.AuthenticationMiddleware:會給request添加一個user對象的中間件。
  7. django.middleware.csrf.CsrfViewMiddleware:CSRF保護的中間件。
  8. django.middleware.clickjacking.XFrameOptionsMiddleware:作clickjacking攻擊的保護。(clickjacking保護是攻擊者在本身的病毒網站上,寫一個誘惑用戶點擊的按鈕,而後使用 iframe 的方式將受攻擊的網站(好比銀行網站)加載到本身的網站上去,並將其設置爲透明的,用戶就看不到,再把受攻擊的網站的轉帳按鈕定位到病毒網站的按鈕上,這樣用戶在點擊病毒網站上按鈕的時候,實際上點擊的是受攻擊的網站上的按鈕,從而實現了在不知不覺中給攻擊者轉帳的功能。
  9. 緩存中間件:用來緩存一些頁面的。  
    • django.middleware.cache.UpdateCacheMiddleware。
    • django.middleware.cache.FetchFromCacheMiddleware。

 

內置中間件放置的順序

(中間件的執行是有順序的,他會根據在 MIDDLEWARE 中存放的順序來執行。)

  • SecurityMiddleware:放到最前面。由於這個中間件並不須要依賴任何其餘的中間件。若是你的網站同時支持http協議和https協議,而且你想讓用戶在使用http協議的時候重定向到https協議,那麼就沒有必要讓他執行下面一大串中間件再重定向,這樣效率更高。
  • UpdateCacheMiddleware。
  • GZipMiddleware。
  • ConditionalGetMiddleware。
  • SessionMiddleware。
  • LocaleMiddleware。
  • CommonMiddleware。
  • CsrfViewMiddleware。
  • AuthenticationMiddleware。
  • MessageMiddleware。
  • FetchFromCacheMiddleware。
  • FlatpageFallbackMiddleware。
  • RedirectFallbackMiddleware。

 

自定義中間件

  中間件所處的位置沒有規定。只要是放到項目當中便可。通常分爲兩種狀況,若是中間件是屬於某個app的,那麼能夠在這個app下面建立一個python文件用來存放這個中間件,也能夠專門建立一個Python包,用來存放本項目的全部中間件。建立中間件有兩種方式,一種是使用函數,一種是使用類。

使用函數的中間件

 1 # middlewares.py
 2 def simple_middleware(get_response):
 3       # 這個中間件初始化的代碼
 4 
 5       def middleware(request):
 6           # request到達view的執行代碼
 7 
 8           response = get_response(request)
 9 
10           # response到達瀏覽器的執行代碼
11 
12           return response
13 
14       return middleware

 

使用類的中間件

 1 class SimpleMiddleware(object):
 2       def __init__(self, get_response):
 3           self.get_response = get_response
 4           # 這個中間件初始化的代碼
 5           def __call__(self, request):
 6               # request到達view以前執行的代碼
 7 
 8               response = self.get_response(request)
 9 
10               # response到達用戶瀏覽器以前執行的代碼
11 
12               return response

 

定義在 request 到達視圖函數以前,判斷這個用戶是否登陸,若是已登陸就綁定一個 user對象 到 request 上的中間件:

 1 # 中間件
 2 def front_user_middleware(get_response):
 3     # 執行一些初始化的代碼
 4     print('front_user_middleware中間件初始化的代碼...')
 5     def middleware(request):
 6         print('request到達view以前執行的代碼...')
 7         user_id = request.session.get('user_id')
 8         if user_id:
 9             try:
10                 user = User.objects.get(pk=user_id)
11                 request.front_user = user
12             except:
13                 request.front_user = None
14         else:
15             request.front_user = None
16         # 在這個代碼執行以前的代碼,是request到view以前的代碼
17         response = get_response(request)
18         print('response到達瀏覽器以前執行的代碼...')
19         # response對象到達瀏覽器以前執行的代碼
20         return response

在 settings.MIDDLEWARES 添加該中間件的配置:

1 # settings.py
2 MIDDLEWARE = [
3     --snip--
4     'middlewares.users.user_middleware',
5 ]
相關文章
相關標籤/搜索