Django中級篇(下)
中間件
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 Codee、Memcache緩存(python-memcached模塊)
Memcache緩存(python-memcached模塊)f、Memcache緩存(pylibmc模塊)
Memcache緩存(pylibmc模塊)2、應用
a. 全站使用
全站使用b. 單獨視圖緩存
View Codec、局部視圖使用
局部信號
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中級篇(下)