02 Django之URL路由系統

一. URL配置html

  URL配置就像Django所支撐網站的目錄.它的本質是URL與要爲該URL調用的視圖之間的映射表.你就是以這種方式告訴Django,對於哪一個URL調用的這段代碼.python

  基本格式正則表達式

from django.conf.urls import url
#循環urlpatterns,找到對應的函數執行,匹配上一個路徑就找到對應的函數執行,就再也不往下循環了,並給函數牀底一個參數request,和wsgiref的environ相似,就是請求信息的全部內容
urlpatterns = [
                url(正則表達式,views.函數,{"參數":別名}),
]

    如今廣泛使用Django2.0版本的路由系統,向下兼容1.x版本的語法數據庫

from django.urls import path

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

    參數說明django

  (1) 正則表達式: 一個正則表達式字符串app

  (2) views視圖函數: 一個可調用的對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串函數

  (3) 參數: 可選的要傳遞給視圖函數的默認參數(字典形式)網站

  (4)別名: 一個可選的name參數url

 

二. 正則表達式詳解spa

  基本配置

 

from django .conf.urls import url

from app(應用) import views

urlpatterns = [

    url(r'^articles/2003/$', views.special_case_2003), #思考:
若是用戶想看200四、200五、2006....等,你要寫一堆的url嗎,
是否是在articles後面寫一個正則表達式/d{4}/就行啦,網址裏面輸入
127.0.0.1:8000/articles/1999/試一下看看 url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), #思考,
若是你想拿到用戶輸入的什麼年份,並經過這個年份去數據庫裏面匹配對應年份的文章,你怎麼辦?
怎麼獲取用戶輸入的年份啊,分組/(\d{4})/,一個小括號搞定 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]

  注意事項  

  1. urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則再也不繼續.

  2. 若要從URL中捕獲一個值,只須要在它周圍放置一對圓括號(分組匹配).

  3.不須要添加一個前導的反斜槓(也就是寫在正則最前面的那個/),由於每一個URL都有.例如,應該是^articles而不是^/articles.

  4.每一個正則表達式前面的'r'是可選的但建議加上

  5.^articles& 以什麼開頭以什麼結尾,嚴格限制路徑.

 

  補充說明

# 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項
APPEND_SLASH=True

  Django settings.py配置文件中默認沒有 APPEND_SLASH這個參數,但DJango默認這個參數是APPEND_SLASH = True.其做用是自動在網址結尾加上'/'.其效果就是:咱們定義了urls.py:

from django.conf.urls import url
from app01 import views

urlpatterns = [
        url(r'^blog/$', views.blog),

 

訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。

  若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。

三. 分組命名匹配

  上面的實例使用簡單的正則表達式分組匹配(經過圓括號) 來捕獲URL中的值並以位置參數形式形式傳遞給視圖.

  在更高級的用法中,可使用分組命名匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖.

  在Python的正則表達式中,分組命名正則表達式組的語法(?P<name>pattern),其中name是組的名稱,pattern是要匹配的模式.

  下面是以上URLconf使用命名組的重寫:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),  #主意正則匹配出來的是字符串,
即使是你在url裏邊寫的是2003數字,匹配出來的也是字符串. url(r'^articles/(\d{4})/$', views.year_archive),#year_archive(request,2003),
小括號表示分組,有分組,name這個分組獲得的是用戶輸入的內容,就會做爲對應函數的位置參數傳進去,
別忘了形參要寫兩個. url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),#某年的,
(?P<year>[0-9]{4}),這是命名參數(正則命名匹配),那麼函數year_archive(request,year),
形參名稱必須是year這個名字.並且注意若是你這個正則後面沒有$符號,即使是輸入了月份路徑,
也會被它攔截下來,由於它的正則也能匹配上 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
#某年某月的 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$',
views.article_detail), #某年某月某日的 ]

  這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給試圖函數.

  例如,針對url /articles/2017/12/至關於按如下方式調用視圖函數:

views.month_archive(request, year="2017", month="12"),year和month的位置能夠換,
沒所謂了,由於是按照名字來取數據的.

  URLconf匹配位置

    URLconf在請求的URL上查找,將它當作一個普通的Python字符串.不包括GET和POST參數以及域名.

  例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/。

  在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/

  URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POSTGETHEAD等等 —— 都將路由到相同的函數。

  捕獲的參數永遠都是字符串

    每一個在URLconf中捕獲的參數都做爲一個普通的Python字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式.例如:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

    傳遞到試圖函數views.year_archive()中的year參數永遠是一個字符串類型.

  視圖函數中指定默認值

# urls.py中
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# views.py中,能夠爲num指定默認值
def page(request, num="1"):
    pass

  

  在上面的例子中,兩個URL模式指向相同的view - views.page - 可是第一個模式並無從URL中捕獲任何東西。

  若是第一個模式匹配上了,page()函數將使用其默認參數num=「1」,若是第二個模式匹配,page()將使用正則表達式捕獲到的num值。

  include其餘的URLconfs(也叫URL分發)

  問你們一個問題,views和models文件是否是都放在每個app應用裏面了啊,而urls.py這個文件放在哪了,是否是放在項目文件夾裏面了,說明什麼,說明是否是全部的app都在使用它,若是你一個項目有10個應用,每一個應用有100個url,那意味着你要在urls文件裏面要寫多少條url對應關係,而且全部的app的url都寫在了這一個urls文件裏面啊,這樣好嗎,固然也沒有問題,可是耦合程度過高了,因此django在url這裏給你提供了一個分發接口,叫作include.

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),  # 能夠包含其餘的URLconfs文件
   url(r'^app01/',include('app01.urls')),#別忘了要去app01這個應用下建立一個urls.py
的文件,如今的意思是凡是以app01開頭的路徑請求,都讓它去找app01下面的urls文件中去找對應的視圖函數
,還要注意一點,此時的這個文件裏面的那個app01路徑不能用$結尾,由於若是寫了$,
就沒辦法匹配app01/後面的路徑了.

  

app01的urls.py的內容:(其實就是將全局的urls.py裏面的內容copy一下,放到你在app01文件夾下建立的那個urls.py文件中,把不是這個app01應用的url給刪掉就好了)

 
from django.conf.urls import url
#from django.contrib import admin
from app01 import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^articles/2003/', views.special_case_2003,{'foo':'xxxxx'}),
    url(r'^articles/(\d{4})/(\d{2})/', views.year_archive),

]

     若是咱們想經過輸入http://127.0.0.1:8000/app01/,看到app01這個應用的首頁,怎麼辦?就像我如今輸入一個http://127.0.0.1:8000來查看網站的首頁,怎麼辦,也就是說我後面不加任何路徑,就看你網址的首頁,怎麼辦,通常網站的根路徑都是網站的首頁,對不對

看下面這種寫法可不能夠:

 

 views.py裏面寫函數index:

 

輸入網址:

  發現都跑到index這個函數裏面去執行了,也就是說,所有被這個沒有匹配規則的url獲取到了.

  因此正確寫法,匹配根路徑的解法:

url(r'^$',views.index),#以空開頭,還要以空結尾,寫在項目的urls.py文件裏面就是項目的首頁,寫在應用文件夾裏面的urls.py文件中,那就是app01的首頁.

  還有注意一點,就是加app的時候,須要進行配置:(startapp app名字)

 

四.命名URL(別名) 和 URL的反向解析

   

    簡單來講就是能夠給咱們的URL匹配規則起個名字,一個URL匹配模式起一個名字。這樣咱們之後就不須要寫死URL代碼了,只須要經過名字來調用當前的URL。

  舉個簡單的例子:

url(r'^home', views.home, name='home'),  #給個人url匹配模式起名(別名)爲home,別名不須要改,
路徑你就能夠隨便改了,別的地方使用這個路徑,就用別名來搞. url(r'^index/(\d*)', views.index, name='index'), # 給個人url匹配模式起名爲index

  在模板裏這樣引用:

{% url 'home' %}  #模板選擇的時候,被django解析成了這個名字對應的url,這個過程叫作反向解析

  在views函數中能夠這樣引用:(後面再講這個視圖函數應用反向解析的內容,上面的是模板應用反向解析的過程)

from django.urls import reverse

reverse("index", args=("2018", ))

  例子:(考慮下面的URLconf)

from django.conf.urls import url

from . import views

urlpatterns = [
    # ...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    # ...
]

  

根據這裏的設計,某一年nnnn對應的歸檔的URL是/articles/nnnn/

  你能夠在模板的代碼中使用下面的方法得到它們:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

<ul>
{% for yearvar in year_list %}
<li>
<a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }}Archive</a>
</li>
</ul>

  在Python 代碼中,這樣使用:

from django.urls import reverse
from django.shortcuts import redirect

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return redirect(reverse('news-year-archive', args=(year,)))

  

  若是出於某種緣由決定按年歸檔文章發佈的URL應該調整一下,那麼你將只須要修改URLconf 中的內容。

  在某些場景中,一個視圖是通用的,因此在URL 和視圖之間存在多對一的關係。對於這些狀況,當反查URL 時,只有視圖的名字還不夠。

  注意

  

爲了完成上面例子中的URL 反查,你將須要使用命名的URL 模式。URL 的名稱使用的字符串能夠包含任何你喜歡的字符。不僅限制在合法的Python 名稱。

  當命名你的URL 模式時,請確保使用的名稱不會與其它應用中名稱衝突。若是你的URL 模式叫作comment,而另一個應用中也有一個一樣的名稱,當你在模板中使用這個名稱的時候不能保證將插入哪一個URL。

  在URL 名稱中加上一個前綴,好比應用的名稱,將減小衝突的可能。咱們建議使用myapp-comment 而不是comment

相關文章
相關標籤/搜索