Django路由層
路由層
當⽤戶在您的Web應⽤程式上發出⻚⾯請求時,Django會獲取url中請求路徑(端 ⼝之後的部分),然後通過urls.py⽂件查詢與路徑相匹配的檢視,然後返回HTML 響應或404未找到的錯誤(如果未找到)。在urls.py中,最重要的是 urlpatterns
列表。這是您定義URL和檢視之間對映的地⽅。對映是URL模式中的path物件
1、路由匹配
from django.conf.urls import patterns, include from app import views urlpatterns = [ path('hello/', views.hello, name='hello'), path('blog/', include('blog.urls')), ]
path物件有四個引數
-
模式串:匹配⽤戶請求路徑的字串(和flask⼀樣)
-
檢視函式:匹配上⽤戶指定請求路徑後調⽤的是檢視函式名 kwargs:
-
可選引數,需要額外傳遞的引數,是⼀個字典
-
名稱(name):給路由命名,在程式碼中可以使⽤name進⾏反向解析(由 name獲取⽤戶請求路勁)。
另外,如果path中模式串如果不能滿⾜你路由規則,還可以使⽤re_path物件, re_path物件中模式串是正則表示式,其他三個引數和path物件⼀致.
#路由匹配 re_path('test/',views.test), re_path('testadd/',views.testadd) """ re_path第一個引數是正則表示式 只要第一個引數正則表示式能夠匹配到內容,那麼就會立刻停止往下匹配,直接執行對應的檢視函式 在輸入url會預設加斜槓,是應為django內部自動做了重定向 """
在path中使⽤<引數名>表示所傳引數,檢視函式中的引數名必須和<>中引數名⼀ 致,引數可以是以下型別:
str:如果沒有指定引數型別,預設是字串型別。字串引數可以匹配除/和
空字元外的其他字串
int:匹配0和正整數,檢視函式的引數將得到⼀個整型值
slug:匹配由數字、字⺟、-和_組成的字串引數
path:匹配任何⾮空字串,包括/。
- string
# 總路由 urlpatterns = [ path('admin/', admin.site.urls), # 路由分發,根路由中包含子路由 # blog/ 路由字首 path('blog/', include('App.urls')), ] # 子路由 # string path('change/<name>/', views.change, name='change'), # path第三個引數name是路由的名字,與檢視函式引數name無關 # views.py def change(request, name): return HttpResponse(name)
效果圖:
- int
# 子路由
urlpatterns = [
# int
path('show/<int:age>/', views.show, name='show')
]
# views.py
def show(request, age):
print(type(age))
return HttpResponse(str(age))
效果圖:
- slug
# 子路由
path('list/<slug:name>/', views.list, name='list')
# views.py
def list(request,name):
print(name,type(name))
return HttpResponse(name)
效果如圖:
- path
# 子路由
# path,如果有多個引數,path型別必須在最後一個
path('access/<path:path>/',views.access,name='access')
# views.py
def access(request, path):
# path 可以包含任何字元,包括 /
return HttpResponse(path)
效果如圖:
Django檢查url模式之前會移除模式前的/
,所以url模式前⾯的/
可以不寫,但如果 在位址列⾥請求的時候不帶尾斜槓,則會引起重定向,重定向到帶尾斜槓的地址, 所以請求的時候要帶尾斜槓。
django路由匹配 的時候其實可以匹配兩次,第一次如果url後面沒有加斜槓,django會讓瀏覽器加斜槓在傳送一次請求
# settings.py
APPEND_SLASH = False# 取消自動加斜槓,預設是True
"""取消了自動加斜槓後,再次訪問瀏覽器就會報錯"""
re_path
中模式包含了⼀ 個上尖括號(^
)和⼀個美元符號($
)。這些都是正則符號,上尖括號表示從字串開 頭匹配。美元符號表示匹配字串的結尾,這兩個符號和到⼀起就表示模式必須完 全匹配路徑,⽽不是包含⼀部分。⽐如對於模式:
r'^hello/$'
如果不包含美元符,也就是r'^hello/'
,任何以/hello/的url都可以 匹配,例如:/hello/world/、/hello/1/2/等,同樣如果不以上尖括號開頭,則任何 以hello/做結尾的url都可以匹配。
# urls.py
from django.contrib import admin
from django.urls import path, re_path
from app03 import views
urlpatterns = [
#首頁
re_path(r'^$',views.home),
#路由匹配
re_path(r'^test/$',views.test),
re_path(r'^testadd/$',views.testadd),
#尾頁
# re_path(r'',views.error),
]
模式匹配的時候要注意:
- Django從上往下進⾏模式匹配,⼀旦匹配成功就不會往下繼續匹配了 ⼀個檢視函式可以有多個模式匹配
- 模式前⾯不需要加
/
- 如果匹配不上,則會引起異常,Django會調⽤錯誤處理檢視處理(關閉除錯模式)
2、無名/有名分組
在re_path中,()部分是正則的組, django在進⾏url匹配時,就會⾃動把匹配 成功的內容,作為引數傳遞給檢視函式。
無名
- 無名分組就是將括號內正則表示式匹配到的內容當作位置引數傳遞給後面的檢視函式
"""
分組:就是給某一個正則表示式用小括號括起來
"""
#urls.py
re_path(r'^test/(\d+)',views.test),
#views.py
def test(request,xxx):
print(xxx)
return HttpResponse('test')
#
有名
- 有名分組就是將括號內正則表示式匹配到的內容當作關鍵字引數傳遞給後面的檢視函式
"""
可以給正則表示式起別名
對正則表示式分組進⾏命名
"""
#urls.py
re_path(r'^testadd/(?P<year>\d+)', views.testadd),
#views.py
def testadd(request, year):
print(year)
return HttpResponse('testadd')
匹配/分組演算法:
- 在⼀個匹配模式中要麼使⽤命名分組,要麼使⽤⽆命名分組,不能同時使⽤
- 請求的URL被看做是⼀個普通的Python 字串, URLconf在其上查詢並匹 配。進⾏匹配時將不包括GET或POST請求⽅式的引數以及域名。換句話講, 對同⼀個URL的⽆論是POST請求、GET請求、或HEAD請求⽅法等等 —— 都 將路由到相同的函式。
- 每個捕獲的引數都作為⼀個普通的Python 字串傳遞給檢視,⽆論正則表達 式使⽤的是什麼匹配⽅式。
# 無名有名 不能混用
re_path(r'^demo/(\d+)/(?P<year>\d+)/',views.demo)
def demo(request, xx, year):
print(xx, year)
return HttpResponse('無名有名混用') 報錯,結果報錯
*************************************************************************************
# 單個分組可以使用多次
* 無名
re_path(r'^demo/(\d+)/(\d+)/',views.demo)
def demo(request, *args):
print(args)
return HttpResponse('demo')
* 有名
re_path(r'^demo/(?P<year>\d+)/(?P<month>\d+)/',views.demo)
def demo(request, *args,**kwargs):
print(kwargs)
return HttpResponse('demo')
3、反向解析
#通過一些方法得到一個結果,該結果可以直接訪問對應的url觸發檢視函式
# 1.先給路由和檢視函式起別名
re_path(r'^func/',views.func,name='zs'),
# 2.反向解析
#後端反向解析
from django.shortcuts import reverse
def home(request):
print(reverse('zs'))
return render(request,'home.html')
#前端反向解析
<a href="{% url 'zs' %}">111</a>
"""別名不能出現衝突!!!"""
4、無名有名反向解析
#無名分組的反向解析
re_path(r'^index/(\d+)/',views.index,name='zs'),
#前端
<a href="{% url 'zs' 1 %}"></a>
#後端
from django.shortcuts import reverse
def home(request):
print(reverse('zs',args=(1,))) #/index/1/
return render(request,'home.html')
"""
數字 一般放的是資料的主鍵值, 來做資料的編輯和刪除
"""
# 有名分組反向解析
re_path(r'^func/(?P<year>\d+)/',views.func,name='li'),
#前端
<a href="{% url 'li' year=123 %}"></a>
#簡單寫法
<a href="{% url 'li' 123 %}"></a>
#後端
def home(request):
print(reverse('li',kwargs={'year':123}))
#簡單寫法
# print(reverse('li', args=(123,)))
return render(request, 'home.html')
5、路由分發
"""
Django的每一個應用都可以有自己的templates資料夾,urls.py static資料夾
正是基於上述的特點,Django能夠非常好的做到多人分組開發,(每個人只寫自己的app)
當一個django專案中的url特別多,總路由urls.py程式碼就非常冗餘,不易於維護,
這個時候就可以利用路由分發,減輕總路由壓力
利用路由分發之後,總路由不再幹路由與檢視函式的直接對應關係
而是做一個分發處理
識別當前url屬於哪個應用下的,直接分發給對應的應用去處理
"""
"""總路由"""
from app01 import urls as app01_urls
from app02 import urls as app02_urls
from django.urls import path, re_path, include
urlpatterns = [
# 1.第一種方式 路由分發
#re_path(r'^app01/', include(app01_urls)), # 只要re_path字首是app01開頭的,全部交給app01處理
#re_path(r'^app02/', include(app02_urls)), # 只要re_path字首是app02開頭的,全部交給app02處理
# 2.第二宗方式 路由分發,不用導模組,
re_path(r'^app01/',include('app01.urls')),
re_path(r'^app02/',include('app02.urls'))
#總路由裡面的re_path不能加$結尾
]
"""子路由"""
#app01下urls.py
from django.urls import path, re_path
from app01 import views
urlpatterns = [
re_path(r'^register/',views.register)
]
#app02下urls.py
from django.urls import path, re_path
from app02 import views
urlpatterns = [
re_path(r'^register/',views.register)
]
6、名稱空間
# 當多個應用出現了相同的別名,反向解析不能自動識別應用字首
#名稱空間
#總路由
path('app01/', include('app01.urls', namespace='app01')),
path('app02/', include('app02.urls', namespace='app02'))
#解析的時候
#後端
#app01下的urls.py
urlpatterns = [re_path(r'^register/',views.register,name='reg')]
#app02下的urls.py
urlpatterns = [re_path(r'^register/',views.register,name='reg')]
#前端
{% url 'app01:reg' %}
{% url 'app02:reg' %}
#只要保證名字不衝突,就沒有必要使用名稱空間
"""
一般情況下,有多個app的時候,在起別名時會加上app的字首
這樣就能確保多個app之間名字不衝突
"""
#加字首
urlpatterns = [
re_path(r'^register/',views.register,name='app02_reg')
]
urlpatterns = [
re_path(r'^register/',views.register,name='app01_reg')
]
7、偽靜態
"""
將一個動態網頁為偽裝成靜態網頁
偽裝的目的在於增大網站的 seo查詢力度
並且增加搜友引擎收藏本網站的概率
搜尋引擎本質上就是一個巨大的爬蟲引擎
"""