1. 程式人生 > >Django視圖層之路由配置系統(urls)

Django視圖層之路由配置系統(urls)

solver hid 頁面 abs 模板 django 可選 之路 ati

視圖層之路由配置系統(urls)

URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。

    ‘‘‘
    
    urlpatterns = [
         url(正則表達式, views視圖函數,參數,別名),
]


參數說明:

    一個正則表達式字符串
    一個可調用對象,通常為一個視圖函數或一個指定視圖函數路徑的字符串
    可選的要傳遞給視圖函數的默認參數(字典形式)
    一個可選的name參數 

    
‘‘‘

正則字符串參數

1 簡單配置

from django.conf.urls import url

from . import views

urlpatterns = [
  url(r‘^admin/‘, admin.site.urls),   #系統生成的映射
 url(r"^$",views.index),  #訪問http://127.0.0.1:8000時,調用index視圖函數,根目錄地址訪問 url(r
^articles/2003/$, views.special_case_2003),  #表示articles/2003/這個路徑映射views模塊的special_case_2003函數
url(r
^articles/([0-9]{4})/$, views.year_archive),  #表示匹配4個0-9的任意數字 url(r^articles/([0-9]{4})/([0-9]{2})/$, views.month_archive), url(r^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$, views.article_detail), ]

#註意:上面匹配都加了小括號,這些括號裏面的值會當作參數傳遞到後面的視圖函數中
‘‘‘
    NOTE:
    1 一旦匹配成功則不再繼續
    2 若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
3 不需要添加一個前導的反斜杠,因為每個URL 都有。例如,應該是^articles 而不是 ^/articles。 4 每個正則表達式前面的‘r‘ 是可選的但是建議加上。 一些請求的例子: /articles/2005/3/ 不匹配任何URL 模式,因為列表中的第三個模式要求月份應該是兩個數字。 /articles/2003/ 將匹配列表中的第一個模式而不是第二個,因為模式按順序匹配,第一個會首先測試是否匹配,匹配成功則不再進行匹配。 /articles/2005/03/ 請求將匹配列表中的第三個模式。
              Django 將調用函數  views.month_archive(request, ‘2005‘, ‘03‘)。 按位置傳參
‘‘‘
技術分享
#設置項是否開啟URL訪問地址後面不為/跳轉至帶有/的路徑
APPEND_SLASH=True
SLASH

2 有名分組(named group)

上面的示例使用簡單的、沒有命名的正則表達式組(通過圓括號)來捕獲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(r^articles/(?P<year>[0-9]{4})/$, views.year_archive),
    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),
]

這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字參數而不是位置參數傳遞給視圖函數。例如:

    /articles/2005/03/    
    請求將調用views.month_archive(request, year=2005, month=03)函數
    /articles/2003/03/03/ 
    請求將調用函數views.article_detail(request, year=2003, month=03, day=03)。

在實際應用中,這意味你的URLconf 會更加明晰且不容易產生參數順序問題的錯誤 —— 你可以在你的視圖函數定義中重新安排參數的順序。當然,這些好處是以簡潔為代價;有些開發人員認為命名組語法醜陋而繁瑣。

如果給路徑命名了,那麽對應的視圖函數中,必須按照該命名作為形參。

註意:

  無論正則表達式使用的是什麽匹配方式,每個捕獲的參數都作為一個普通的Python 字符串傳遞給視圖

例如,下面這行URLconf 中:

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

  views.year_archive()year 參數將是一個字符串

3 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等等 —— 都將路由到相同的函數。

4 指定視圖參數的默認值

有一個方便的小技巧是指定視圖參數的默認值。 下面是一個URLconf 和視圖的示例:

# URLconf
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),
]

# View (in blog/views.py)
def page(request, num="1"):

    ...

在上面的例子中,兩個URL模式指向同一個視圖views.page —— 但是第一個模式不會從URL 中捕獲任何值。如果第一個模式匹配,page() 函數將使用num參數的默認值"1"。如果第二個模式匹配,page() 將使用正則表達式捕獲的num 值。

別名

urlpatterns = [
    url(r^reg/$, views.month_views,name=register),
]

而在訪問的靜態文件中,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>

</head>
<body>
  <form method=post action={% register %}>xxxx</form>
</body>
</html>

當我們後端的路徑發生變化時(即匹配規則^reg/$需要改動時),直接改動,前端的頁面如果引用別名{% register %},則可不用改變前端任何代碼,都能夠正常映射訪問。

URL 的反向解析

  獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。

Django 提供一個辦法是讓URL 映射是URL 設計唯一的地方。你填充你的URLconf,然後可以雙向使用它:

  • 根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數需要的值。
  • 根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。

第一種方式是我們在前面的章節中一直討論的用法。第二種方式叫做反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查。

在需要URL 的地方,對於不同層級,Django 提供不同的工具用於URL 反查:

  • 在模板中:使用url 模板標簽。
  • 在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。
  • 在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。

例子:

考慮下面的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>
{% endfor %}
</ul>

在Python 代碼中,這樣使用:

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

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

如果出於某種原因決定按年歸檔文章發布的URL應該調整一下,那麽你將只需要修改URLconf 中的內容。

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

命名URL 模式

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

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

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

CBV

技術分享
url(r^login.html$, views.Login.as_view()),
 
============================
from django.views import View
class Login(View):
     
    def dispatch(self, request, *args, **kwargs):
        print(before)
        obj = super(Login,self).dispatch(request, *args, **kwargs)
        print(after)
        return obj
 
    def get(self,request):
        
        return render(request,login.html)
 
    def post(self,request):
        print(request.POST.get(user))
        return HttpResponse(Login.post)
View Code

路由應用分發

  如果一個網站很多,有很多app應用,那麽就需要很多路由分發。如果將所有的路由分發都放在urlconf文件下,這樣會使得文件不易於管理,為此,我們可以給每一個app都創建一個urls.py文件,然後再urlconf中的urlpatterns中將該urls.py文件包含進來就行了。

from django.conf.urls import include, url # 導入全局url
urlpatterns = [
    url(r^blog, include(blog.urls)),   #將訪問路徑以blog開頭的路徑分發到app1下的urls.py模塊裏進行路由映射
]

  這樣在我們blog-app中的url中,存放所有關於blog的url分發工作。

urlpatterns = [
    url(r^2004/$, year_2004),     
    url(r^(\d{4})/$, year_query),     
    url(r^(\d{4})/(\d{2})$, year_query),     
    url(r^(?P<year>\d{4})/(?P<month>\d{2})$, year_query),    
]

這樣我們訪問網站應該是:http://127.0.0.1:8080/blog/2012/3 前面都得帶上app的名稱

Django視圖層之路由配置系統(urls)