1. 程式人生 > >Django中級篇(下)

Django中級篇(下)

dump signal nec 檢測 == csr providing https messages

中間件

django 中的中間件(middleware),在django中,中間件其實就是一個類,在請求到來和結束後,django會根據自己的規則在合適的時機執行中間件中相應的方法。

MIDDLEWARE_CLASSES = [
    # ‘ZHONGJIANJIAN.text.text1Middleware‘,   #自定義中間件
    ‘django.middleware.security.SecurityMiddleware‘,
    ‘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‘,
]

中間件中可以定義四個方法,分別是:

process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

以上方法的返回值可以是None和HttpResonse對象,如果是None,則繼續按照django定義的規則向下執行,如果是HttpResonse對象,則直接將該對象返回給用戶

技術分享

djanjo 中間件版本差異報錯處理:

1.9.x版本以下djanjo中間件定義規則

class CommonMiddleware(object):
    def process_request(self, request):
        return None
 
    def process_response(self, request, response):
        return response
		

最新的1.10.x版本djanjo中間件定義規則----------不是執行的類下的方法,而是執行MiddlewareMixin對象的__call__方法(方法中調用,process_request等方法)

from djanjo.utils.deprecation import MiddlewareMixin
class CommonMiddleware(MiddlewareMixin):
    def process_request(self, request):
        return None
 
    def process_response(self, request, response):
        return response

下面的方法就可以讓 中間件 兼容 Django新版本和舊版本------------上面倆種的合並

__call__ 方法會先調用 self.process_request(request),接著執行 self.get_response(request) 然後調用 self.process_response(request, response)

try:
    from django.utils.deprecation import MiddlewareMixin  # Django 1.10.x
except ImportError:
    MiddlewareMixin = object  # Django 1.4.x - Django 1.9.x
 
 
class SimpleMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass
 
    def process_response(request, response):
        pass

新版本中 django.utils.deprecation.MiddlewareMixin 的 源代碼 如下:

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()
 
    def __call__(self, request):
        response = None
        if hasattr(self, ‘process_request‘):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, ‘process_response‘):
            response = self.process_response(request, response)
        return response

功效:

比如我們要做一個 攔截器,比如統計一分鐘訪問頁面數,太多就把他的 IP 加入到黑名單 BLOCKED_IPS,發現有惡意訪問網站的人,就攔截他!

class BlockedIpMiddleware(object):
    def process_request(self, request):
        if request.META[‘REMOTE_ADDR‘] in getattr(settings, "BLOCKED_IPS", []):
            return http.HttpResponseForbidden(‘<h1>Forbidden</h1>‘)

中間件生命周期(1.9.x版本以下):

技術分享

1>正常情況(有倆個中間件的情況

process_request1---->process_request2---->process_view1------process_view2----->url---->views---> process_response2----->process_response1

2>在任意一個process_request中只要有return直接跳到process_response

process_request1---->process_request2----> process_response2----->process_response1

3>如果返回值中有render的話走process_template_response

process_request1---->process_request2---->process_view1------process_view2----->url---->views--->process_template_response2---->

process_template_response1--->process_response2----->process_response1

4>views中出現錯誤的時候走process_exceptionprocess_response

process_request1---->process_request2---->process_view1--->process_view2----->url---->views---> process_exceptionprocess_response2--->

process_exceptionprocess_response1

技術分享

中間件生命周期(1.10.x版本及以上):

和1.9.x版本以下相比,不同點在於,當request中出現return的時候,直接到最外層的response,而不經過裏層的response

自定義中間件

1、創建中間件類

class RequestExeute(object):

    def process_request(self,request):

        pass

    def process_view(self, request, callback, callback_args, callback_kwargs):

        i =1

        pass

    def process_exception(self, request, exception):

        pass
      
    def process_response(self, request, response):

        return response

2、註冊中間件

MIDDLEWARE_CLASSES = (

    ‘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‘,

    ‘wupeiqi.middleware.auth.RequestExeute‘,

)

緩存

由於Django是動態網站,所有每次請求均會去數據進行相應的操作,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則不再去執行view中的操作,而是直接從內存或者Redis中之前緩存的內容拿到,並返回

Django中提供了6種緩存方式:

  • 開發調試
  • 內存
  • 文件
  • 數據庫
  • Memcache緩存(python-memcached模塊)
  • Memcache緩存(pylibmc模塊)

1、配置

a、開發調試

技術分享 開發調試

b、內存

技術分享 內存

c、文件

技術分享 文件

d、數據庫

技術分享 View Code

e、Memcache緩存(python-memcached模塊)

技術分享 Memcache緩存(python-memcached模塊)

f、Memcache緩存(pylibmc模塊)

技術分享 Memcache緩存(pylibmc模塊)

2、應用

a. 全站使用

技術分享 全站使用

b. 單獨視圖緩存

技術分享 View Code

c、局部視圖使用

技術分享 局部

信號

Django中提供了“信號調度”,用於在框架執行操作時解耦。通俗來講,就是一些動作發生的時候,信號允許特定的發送者去提醒一些接受者。

1、Django內置信號

Model signals

    pre_init                    # django的modal執行其構造方法前,自動觸發

    post_init                   # django的modal執行其構造方法後,自動觸發

    pre_save                    # django的modal對象保存前,自動觸發

    post_save                   # django的modal對象保存後,自動觸發

    pre_delete                  # django的modal對象刪除前,自動觸發

    post_delete                 # django的modal對象刪除後,自動觸發

    m2m_changed                 # django的modal中使用m2m字段操作第三張表(add,remove,clear)前後,自動觸發

    class_prepared              # 程序啟動時,檢測已註冊的app中modal類,對於每一個類,自動觸發

Management signals

    pre_migrate                 # 執行migrate命令前,自動觸發

    post_migrate                # 執行migrate命令後,自動觸發

Request/response signals

    request_started             # 請求到來前,自動觸發

    request_finished            # 請求結束後,自動觸發

    got_request_exception       # 請求異常後,自動觸發

Test signals

    setting_changed             # 使用test測試修改配置文件時,自動觸發

    template_rendered           # 使用test測試渲染模板時,自動觸發

Database Wrappers

    connection_created          # 創建數據庫連接時,自動觸發

對於Django內置的信號,僅需註冊指定信號,當程序執行相應操作時,自動觸發註冊函數:

技術分享 View Code 技術分享 View Code

----註冊的時候我們可以給上面的代碼放到我們創建的project下的__init__.py文件中(或新建一.py文件,最後在__init__中導入)就註冊成功了

2、自定義信號

a. 定義信號

import django.dispatch

pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 註冊信號

def callback(sender, **kwargs):

    print("callback")

    print(sender,kwargs)

pizza_done.connect(callback)

c. 觸發信號

from 路徑 import pizza_done

pizza_done.send(sender=‘seven‘,toppings=123, size=456)

由於內置信號的觸發者已經集成到Django中,所以其會自動調用,而對於自定義信號則需要開發者在任意位置觸發。

序列化

關於Django中的序列化主要應用在將數據庫中檢索的數據返回給客戶端用戶,特別的Ajax請求一般返回的為Json格式。

1、serializers

from django.core import serializers

ret = models.BookType.objects.all()

data = serializers.serialize("json", ret)

2、json.dumps

import json

#ret = models.BookType.objects.all().values(‘caption‘)

ret = models.BookType.objects.all().values_list(‘caption‘)

ret=list(ret)

result = json.dumps(ret)

由於json.dumps時無法處理datetime日期,所以可以通過自定義處理器來做擴展,如:

import json
from datetime import date
from datetime import datetime

class CJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime(‘%Y-%m-%d %H:%M:%S‘)
        elif isinstance(obj, date):
            return obj.strftime("%Y-%m-%d")
        else:
            return json.JSONEncoder.default(self, obj)

用法 : json.dumps(yourdatetimeobj, cls=CJsonEncoder)  

分頁

一、Django內置分頁

Paginator

二、自定義分頁

分頁功能在每個網站都是必要的,對於分頁來說,其實就是根據用戶的輸入計算出應該在數據庫表中的起始位置。

1、設定每頁顯示數據條數

2、用戶輸入頁碼(第一頁、第二頁...)

3、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置

4、在數據表中根據起始位置取值,頁面上輸出數據


需求又來了,需要在頁面上顯示分頁的頁面。如:[上一頁][1][2][3][4][5][下一頁]

1、設定每頁顯示數據條數

2、用戶輸入頁碼(第一頁、第二頁...)

3、設定顯示多少頁號

4、獲取當前數據總條數

5、根據設定顯示多少頁號和數據總條數計算出,總頁數

6、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置

7、在數據表中根據起始位置取值,頁面上輸出數據

8、輸出分頁html,如:[上一頁][1][2][3][4][5][下一頁]

技術分享 分頁

總結,分頁時需要做三件事:

  • 創建處理分頁數據的類
  • 根據分頁數據獲取數據
  • 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]

文件上傳

a、自定義上傳

def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get(‘fafafa‘)
        f = open(obj.name, ‘wb‘)
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
    return render(request, ‘file.html‘)

b、Form上傳文件實例

技術分享 View Code 技術分享 View Code 技術分享 View Code

Django中級篇(下)