第十一章——常用的Web應用程式
django常用的Web程式
會話機制
當用戶第一次訪問網站時,網站的伺服器將自動建立一個Session物件,該Session物件相當於該使用者在網站的一個身份憑證,而且Session能儲存該使用者的資料資訊。當用戶在網站的頁面之間跳轉時,儲存在Session物件中的資料不會丟失,只有Session過期或被清理時,伺服器才將Session中儲存的資料清空,並終止該Session.
當獲取某使用者的Session資料時,首先從使用者傳遞的Cookie裡獲取sessionid,然後根據sessionid在網站伺服器找到相應的Session。
Session存放在伺服器的記憶體中,因此存放在Session中的資料不能過於龐大。
每個使用者的Session通過Django的中介軟體MIDDLEWARE接收和排程處理
django.contrib.sessions.middleware.SessionMiddleware
當訪問網站時,所有的HTTP請求都經過中介軟體處理,中介軟體SessionMiddleware
相當於HTTP請求接收器,根據請求資訊做出相應的排程,而程式的執行則由settings.py的配置屬性INSTALLED_APPS中django.contrib.sessions
完成。
django.contrib.sessions實現了Session的建立和操作處理,如建立或儲存使用者的Session物件,管理Session的生命週期等,它預設使用資料庫儲存Session資訊,資料庫名為django_session
變更Session的儲存方式
Session預設儲存在資料庫中,變更的話可在settings.py中新增配置資訊SESSION_ENGINE,該配置可以指定Session的儲存方式。
django提供5種Session的儲存方式
# 資料庫儲存方式,django預設,無需再settings.py中設定 SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 以檔案形式儲存 SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 使用文字儲存可設定檔案儲存路徑,有相對路徑和絕對路徑 SESSION_FILE_PATH = '/MyDjango' # /MyDjango代表文字儲存在專案MyDjango的根目錄 # 以快取形式儲存 SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 設定快取名,預設是記憶體快取方式,此處的設定與快取機制的設定有關 SESSION_CACHE_ALIAS = 'default' # 以資料庫+快取形式儲存 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 以Cookie形式儲存 SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
設定瀏覽器中的Cookie相關資訊
也是通過伺服器後端的Session設定的
比如Cookie的生命週期,傳輸方式或儲存路徑等
待補
Session的讀寫操作
Session的資料型別可理解為Python的字典型別,主要在檢視函式中進行讀寫,從使用者請求中獲取(來自檢視函式的request)
待補
使用會話實現商品搶購(重點)
他的會話儲存實現兩個頁面事件的資料傳遞,這個我並未弄清楚
筆記待補
快取機制
當網站訪問過大時,網站的響應速度必然大大降低,知識和可以在網站上使用快取機制。
快取是將一個請求的響應內容儲存到記憶體、資料庫、檔案或者快取記憶體系統(Memcache)中,若某個事件再次接收同一個請求,則不再執行該請求的響應過程,而是直接從記憶體或者快取記憶體系統中獲取該請求的響應內容返回給使用者。
快取的方式與配置
django提供5種不同的快取方式
待補
每種快取方式都需結合網站的實際情況而定。若在專案中使用快取機制,則首先在配置檔案settings.py中設定快取的相關配置.
# 每種快取方式的配置
快取配置的引數BACKEND和LOCATION是必選引數,其餘的配置引數可自行選擇。
完整的資料庫快取配置
CACHES = {
# 預設快取資料表
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
# TIMEOUT設定快取的生命週期,以秒為單位,若為None,則永不過期
'TIMEOUT': 60,
'OPTIONS': {
# MAX_ENTRIES代表最大快取記錄的數量
'MAX_ENTRIES': 1000,
# 當快取到達最大數量之後,設定剔除快取的數量
'CULL_FREQUENCY': 3,
}
},
# 設定多個快取資料表
'MyDjango': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'MyDjango_cache_table',
}
}
DJango允許同時配置和使用多種不同型別的快取方式,配置方法與多資料庫的配置方式類似。快取資料表的建立依賴於資料庫配置settings.py中的DATABASES,如果有多個數據庫,則預設在DATABASES的default的資料庫中生成。
快取的使用
快取的使用方式有4種,主要根據不同的適用物件進行劃分。
全站快取
檢視快取
路由快取
模板快取
全站快取在django的中介軟體中配置,
MIDDLEWARE = [
# 配置全站快取
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# 使用中文
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 配置全站快取
'django.middleware.cache.FetchFromCacheMiddleware',
]
# 設定快取的生命週期
CACHE_MIDDLEWARE_SECONDS = 15
# 設定快取資料儲存在資料表my_cache_table中
# 屬性值default來自於快取配置CACHES的default屬性
CACHE_MIDDLEWARE_ALIAS = 'default' # 設定快取的路徑
# 設定快取表字段cache_key的值
# 用於同一個Django專案多個站點之間的共享快取
CACHE_MIDDLEWARE_KEY_PREFIX = 'MyDjango' # 指定某個站點的名稱
檢視快取
在檢視函式或檢視類的執行過程中生成快取資料,檢視使用裝飾器生成,並儲存快取資料。
裝飾器設有引數timeout,cache,key_prefix,引數timeout是必選引數,其餘兩個引數是可選引數。引數的作用與全域性快取的配置屬性相同
from django.shortcuts import render
# 匯入cache_page
from django.views.decorators.cache import cache_page
# 引數cache與配置屬性CACHE_MIDDLEWARE_ALIAS相同
# 引數key_prefix與配置屬性CACHE_MIDDLEWARE_KEY_PREFIX相同
# 引數timeout與配置屬性CACHE_MIDDLEWARE_SECONDS相同
# CACHE_MIDDLEWARE_SECONDS的優先順序高於引數timeout
@cache_page(timeout=10, cache='MyDjango', key_prefix='MyView')
def index(request):
return render(request, 'index.html')
路由快取
在路由檔案urls.py中生成和儲存的,路由快取也是使用快取函式cache_page實現的。
from django.views.decorators.cache import cache_page
urlpatterns = [
# 網站首頁設定路由快取
path('', cache_page(timeout=10, cache='MyDjango', key_prefix='MyURL')(views.index), name='index'),
# path('', views.index, name='index'),
]
模板快取
模板快取是通過Django的快取標籤實現的,快取標籤可以設定快取的生命週期、快取的關鍵詞和快取資料表(函式cache_page的引數timeout、key_prefix和cache),三者的設定順序和程式碼格式是固定不變的。
<div>
{# 設定模版快取 #}
{% load cache %}
{# 10代表生命週期 #}
{# MyTemp代表快取資料的cache_key欄位 #}
{# using="MyDjango"代表快取資料表 #}
{% cache 10 MyTemp using="MyDjango" %}
<div>Hello Django</div>
{# 快取結束 #}
{% endcache %}
</div>
CSRF防護
CSRF防護只適用於POST請求,並不防護GET請求,因為GET請求是以只讀形式訪問網站資源的,一般情況下不會破壞和篡改網路資料。
防護是採用模板語法{% csrf_token %}生成一個隱藏的控制元件
<input type="hidden" name="csrfmiddlewaretoken" value="zUJfhT41OyX80zCqbbytV4Lc5hoQgATmg5wTeh4XnpnBrbaSytkvw0WUcNC0Dtfd">
隱藏控制元件的屬性value值實用Django隨機生成的,當用戶提交表單時,django會校驗表單的csrfmiddlewaretoken是否於自己儲存的csrfmiddlewardtoken一致,使用者每次提交表單時,隱藏控制元件的屬性value都會隨之變化。
取消CSRF防護
刪除模板檔案的{% csrf_token %},並且在對應的檢視函式中新增裝飾器@csrf_exempt
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.csrf import csrf_exempt
# 新增CSRF防護
# @csrf_protect
# 取消CSRF防護
@csrf_exempt
def index(request):
return render(request, 'index.html')
若並未在對應檢視函式中新增裝飾器@csrf_exempt
,那麼使用者在提交表單時,程式會因CSRF驗證失敗而丟擲403異常的頁面。
若想全面取消整個網站的CSRF防護,那麼可以在settings.py中MIDDLEWARE註釋掉
django.middleware.csrf.CsrfViewMiddleware
但若想在某些請求上設定CSRF防護,在對應的html檔案中加入{% csrf_token %},並在對應的檢視函式中新增裝飾器@csrf_protect
@csrf_protect
def index(request):
return render(request, 'index.html')
如果網頁表單時使用前端的Ajax向Django提交表單資料的,Django設定了CSRF防護功能,Ajax傳送POST請求就必須設定請求引數csrfiddlewaretoken,否則Django會將當前請求視為惡意請求。Ajax傳送POST的請求的功能程式碼如下
待補(很重要)
訊息框架
在網頁應用中,當用戶完成某個功能操作時,網站會有相應的訊息提示。Django內建的訊息框架可以供開發者直接呼叫,它允許開發者設定功能引擎、訊息型別和訊息類容。
訊息框架由中介軟體SessionMiddleware,MessageMiddleware和INSTALLED_APPS中的django.contrib.sessions,django.contrib.messages共同實現。
具體實現
MessageMiddleware(essionMiddleware,,是哪一個中介軟體)的功能引擎預設使用FallbackStorage,而FallbackStorage是在session的基礎上實現的,所以SessionMiddleware中介軟體必須設定在MessageMiddleware前面。
相關資料展現的有些許不同
MessageMiddleware的原始碼位置
待補
MessageMiddleware原始碼檔案所包含的檔案及作用
待補
訊息框架的使用
訊息框架主要在檢視和模板中使用,而且訊息框架在檢視函式和檢視類有著不一樣的使用方式
設定訊息框架的功能引擎
# MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
# MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
# FallbackStorage是預設使用,可以無需設定
MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'
設定url
待補
定義對應的檢視函式
這裡有個上下文處理器,值得注意
待補
分頁功能
分頁功能需要考慮的因素:
1.當前使用者訪問的頁數是否存在上(下)頁
2.訪問的頁數是否超出頁數上限
3.資料如何按頁擷取,如何設定每頁的資料量
主要實現分頁的Paginator類一共定義了4個初始化引數和8個類方法,每個初始化引數和類方法的說明如下
待補
我們將Paginator例項化之後,在由例項化物件呼叫get_page()即可得到Page類的例項化物件。在原始碼檔案paginator.py中可以找到Page類的定義過程,它一共定義了3個初始化引數和7個類方法
待補
使用django的shell模式,簡述使用分頁功能
In [1]: # 匯入分頁功能模組
In [2]: from django.core.paginator import Paginator
In [3]: # 生成資料列表
In [4]: objects = [chr(x) for x in range(97,107)]
In [5]: objects
Out[5]: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
In [6]: # 將資料列表以每3個元素分頁
In [7]: p = Paginator(objects,3)
In [8]: # 輸出全部資料,即整個資料列表
In [9]: p.object_list
Out[9]: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
In [10]: # 獲取資料列表長度
In [11]: p.count
Out[11]: 10
In [12]: 分頁後的總頁數
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-12-b9a482fe307d> in <module>
----> 1 分頁後的總頁數
NameError: name '分頁後的總頁數' is not defined
In [13]: # 分頁後的總頁數
In [14]: p.num_pages
Out[14]: 4
In [15]: # 將頁數轉換為range迴圈物件
In [16]: p.page_range
Out[16]: range(1, 5)
In [17]: # 獲取第二頁的資料資訊
In [18]: page2 = p.get_page(2)
In [19]: # 判斷第二頁上是否還有上一頁
In [20]: page2.has_previous()
Out[20]: True
In [21]: # 判斷第二頁是否存在下一頁
In [22]: page2.has_next()
Out[22]: True
In [23]: # 如果當前頁存在下一頁,就輸出下一頁的頁數
In [24]: # 否則丟擲EmptyPage異常
In [25]: page2.next_page_number()
Out[25]: 3
In [26]: # 如果當前頁存在上一頁,就輸出上一頁的頁數
In [27]: # 否則丟擲EmptyPage異常
In [28]: page2.previous_page_number()
Out[28]: 1
In [29]: # 判斷當前頁是否存在上一頁或者下一頁
In [30]: page2.has_other_pages()
Out[30]: True
In [31]: # 輸出第二頁所對應的資料內容
In [32]: page2.has_other_pages()
Out[32]: True
In [33]: page2.object_list
Out[33]: ['d', 'e', 'f']
In [34]: # 輸出第二頁的第一行資料在整個資料列表的位置
In [35]: # 資料位置從1開始計算
In [36]: page2.start_index()
Out[36]: 4
In [37]: # 輸出第二頁的最後一行資料在整個資料列表的位置
In [38]: # 資料位置從1開始計算
In [39]: page2.end_index()
Out[39]: 6
diango分頁功能的具體使用,主要在views.py中的檢視函式中使用,一般需要在檢視函式中傳入自定義引數來當個page變數例項化,作用在模板檔案上
待補