今日學習內容總結5.0
今日學習內容總結
Django請求生命週期
概述
首先我們知道HTTP請求及服務端響應中傳輸的所有資料都是字串。
在Django中,當我們訪問一個的url時,會通過路由匹配進入相應的html網頁中。
Django的請求生命週期是指當用戶在瀏覽器上輸入url到使用者看到網頁的這個時間段內,Django後臺所發生的事情。
而Django的生命週期內到底發生了什麼呢?
1. 當用戶在瀏覽器中輸入url時,瀏覽器會生成請求頭和請求體發給服務端,請求頭和請求體中會包含瀏覽器的動作(action),這個動作通常為get或者post,體現在url之中。 2. url經過Django中的wsgi,再經過Django的中介軟體,最後url到過路由對映表,在路由中一條一條進行匹配,一旦其中一條匹配成功就執行對應的檢視函式,後面的路由就不再繼續匹配了。 3. 檢視函式根據客戶端的請求查詢相應的資料.返回給Django,然後Django把客戶端想要的資料做為一個字串返回給客戶端。 4. 客戶端瀏覽器接收到返回的資料,經過渲染後顯示給使用者。
整體流程可為下圖:
後續學習內容也就是按照這個流程學習。
路由層之路由匹配
路由匹配的特點
1.只要匹配上了就會立刻結束執行對應的檢視函式。
2.url方法的第一個引數其實是一個正則表示式,只要正則表示式能夠從使用者輸入的字尾中匹配到內容就算匹配上了。
路由匹配
# 路由匹配 url(r'test',views.test), url(r'testadd',views.testadd) """ url方法第一個引數是正則表示式 只要第一個引數正則表示式能夠匹配到內容 那麼就會立刻停止往下匹配 直接執行對應的檢視函式 你在輸入url的時候會預設加斜槓 django內部幫你做到重定向 一次匹配不行 url後面加斜槓再來一次 """ urlpatterns = [ url(r'^admin/', admin.site.urls), # 首頁 url(r'^$',views.home), # 路由匹配 url(r'^test/$',views.test), url(r'^testadd/$',views.testadd), # 尾頁(瞭解) url(r'',views.error), ]
演變分析
1.
正則是test 內容是test 那麼可以匹配出test文字
正則是test 內容是testadd 那麼還可以匹配出test文字
都算匹配上了
2.
正則是test/ 內容是test 那麼首次無法匹配 這時候就會觸發django二次追加斜槓機制 首次匹配不上 那麼django還會讓瀏覽器預設加斜槓再次傳送請求 # 取消自動新增斜槓 "/" 1. 經過測試了路由後面不新增"/"一共匹配了兩次 2. 而自動新增斜槓這種操作是可以取消的 # setting.py 檔案 APPEND_SLASH = False # 預設 True 自動新增斜槓 3. 設定之後如果不新增斜槓就無法訪問資源
3.
正則是test/ 內容是abcdefgtest/ 那麼可以匹配出文字test/
可以在正則的最前面加上上箭頭來限制,解決路由前面可以隨意亂寫的問題
4.
正則是^test/ 內容是test/abc/edf/acd/ 那麼可以匹配出文字test/
可以在正則的最後面加上$來限制,解決路由後面可以隨意亂寫的問題
拓展
由於第一個引數是正則,所以當專案特別大,對應關係特別多的時候要格外的注意是否會出現路由頂替的現象。
1.可以定製一個主頁面,使用者不攜帶字尾可以直接訪問
url(r'^$',views.home)
2.也可定義一個尾頁,使用者輸入一個沒有對應關係的直接返回
url(r'.*',views.error)
無名有名分組
無名分組
url(r'^login/$', views.login_func)
# 無名分組
url(r'^login/(\d+)/$', views.login_func)
# 檢視函式
def login_func(request,*args):
print(args)
return Httpresponse(args)
url( ) 方法中第一個引數正則表示式分組 : 給正則表示式前後加一個小括號
會將括號內正則表示式匹配到的內容當做位置引數傳遞給後邊的檢視函式傳遞一個request位置引數。
如果路由匹配中使用括號對正則表示式進行了分組,那麼在呼叫檢視函式的時候,會將括號內匹配到的內容當做位置引數傳遞給檢視函式。
有名分組
url(r'^login/$', views.login_func)
# 有名分組
url(r'^login/(?P<id>\d+)/$', views.login_func)
# 檢視函式
def login_func(request,**kwargs):
print(kwargs)
return Httpresponse(args)
給括號內的正則表示式起別名之後,匹配成功則會講括號內匹配到的內容按照關鍵字引數傳遞給檢視函式。
有名無名能否結合使用
無名有名分組不能不能結合使用。
url(r'^login/(\d+)/(?P<id>\d+)/$', views.login_func)
# 官方說不能混著用, 混著用只能取到有名分組捕獲的值
# 只要不混著用,有名分組和無名分組支援多個相同型別的傳參
但是可以單個複用。
url(r'^login/(\d+)/(\d+)/$', views.login_func)
url(r'^login/(?P<id>\d+)/(?P<id>\d+)/$', views.login_func)
反向解析
概念
反向解析就是通過一些方法得到一個結果, 該結果可以直接訪問對應的 url 並觸發檢視函式。
作用
1.在使用一個 Django 專案時, 我們經常需要將一個 url 嵌入到生成的內容中去, 如果將這些 url 固定寫死, 那麼可擴充套件性很差, 並且一定程度上會產生過期的 url。
2.使用反向解析就是當路由頻繁變化的時候, 讓 html 介面上的連線地址做到動態解析。
反向解析的使用
1.給路由與檢視函式對應關係新增一個別名 (名字由自己指定, 只要不衝突即可)
# 路由層
url(r'^func666/',views.func,name='func_view')
2.根據該別名可動態解析出一個結果, 該結果可以直接訪問到對應的路由。
# 前端中使用(模板層)
<a href="{% url 'func_view' %}">登入</a> # func666/ 結果可以訪問路由
# 後端中使用(檢視層)
from django.shortcuts import reverse
url = reverse('func_view') # func666/ 結果可以訪問路由
無名分組反向解析
1. 給對應關係起別名
url(r'^func666/(\d+)/',views.func,name='func_view')
2. 使用反向解析獲取結果
前端:
{% url 'func_view' 123 %} # func666/123/
後端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
有名分組反向解析
1.給對應關係起別名
url(r'^func666/(?P<id>\d+)/',views.func,name='func_view')
2.使用反向解析獲取結果
前端:
{% url 'func_view' 123 %} # func666/123/
{% url 'func_view' id=123 %} # func666/123/
後端:
from django.shortcuts import reverse
reverse('func_view',args=(666,)) # func666/666/
reverse('func_view',kwargs={'id':1}) # func666/1/
路由層中分組匹配得到的數字並不是我們這樣寫死的, 一般情況下放的是資料的主鍵值, 我們可以通過獲取到資料的主鍵.進而定位到資料物件, 從而可以對資料進行編輯和刪除。
路由分發
簡介
django是專注於開發應用的,當一個django專案特別龐大的時候, 所有的路由與檢視函式對映關係全部寫在一個 urls.py 裡面很明顯太冗餘並且不便於管理。
其實django中的每一個應用都可以有自己的 urls.py、static資料夾、templates資料夾, 基於上述特點, 使用django做分組開發非常的簡便。
每個人只需要寫自己的應用即可, 最後由組長統一彙總到一個空的django專案中然後使用路由分發將多個應用關聯到一起。
利用路由分發之後, 總路由不再幹路由與檢視函式的直接對應關係, 而是做一個分發處理, 進而識別當前url所屬的應用, 最後直接分發給對應的應用去處理就行了, 並且應用路由重名也無關要緊。
路由分發設定
1.建立多個應用 並去配置檔案中註冊。
INSTALLED_APPS = [
'app01',
'app02'
]
2.在多個應用中編寫相同的路由。
urlpatterns = [
url(r'^index/',views.index111)
]
urlpatterns = [
url(r'^index/',views.index)
]
3.路由分發
from django.conf.urls import url, include
# 方式一 : 複雜寫法
from app01 import urls as app01_ulrs
from app02 import urls as app02_ulrs
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^app01/', include(app01_ulrs)),
re_path(r'^app02/', include(app02_ulrs)),
re_path(r'^app03/', include(app03_ulrs))
]
# 方式二 : 高階寫法
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^app01/', include('app01.ulrs')),
re_path(r'^app02/', include('app02.ulrs')),
re_path(r'^app03/', include('app03.ulrs'))
]
名稱空間
當多個應用設定了相同的別名, 在反向解析的時候前面路由會被後面的路由覆蓋, 那麼就無法觸發前面路由對應的檢視函式, 正常情況下, 反向解析是無法自動識別字首的, 為了避免這種錯誤, 引入了名稱空間
驗證發現預設情況下是不會自動識別應用字首的,如何解決反向解析問題。
方式1:名稱空間
總路由新增名稱空間
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
應用反向解析自動提示
reverse('app01:index_view')
reverse('app02:index_view')
{% url 'app01:index_view' %}
{% url 'app02:index_view' %}
方式2:只需要確保反向解析的別名在整個專案中不重複即可,可以在別名的前面加上應用名的字首
url(r'^index/',views.index,name='app01_index_view')
url(r'^index/',views.index,name='app02_index_view')