1. 程式人生 > >命名URL和URL反向解析

命名URL和URL反向解析

在使用Django專案時,一個常見的需求是獲得URL的最終形式,以用於嵌入到生成的內容中(檢視中和顯示給使用者的URL等)或者用於處理伺服器端的導航(重定向等)。

人們強烈希望不要硬編碼這些URL(費力,不可擴充套件且容易產生錯誤)或者設計一種與URLconf毫不相干的專門的URL生成機制,因為這樣容易導致一定程度上產生過期的URL。

換句話講,需要的是一個DRY機制。除了其它有點,它還允許設計的URL可以自動更新而不用遍歷專案的原始碼來搜尋並替換過期的URL。

獲取一個URL最開始想到的資訊是處理它檢視的標識,查詢正確的URL的其他必要的資訊有檢視引數的型別(位置引數,關鍵字引數)和值。

Django提供一個辦法是讓URL對映到URL設計唯一的地方。

你填充你的URLconf,然後可以雙向使用它:

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

第二種方式叫做反向解析URL、反向URL匹配、反向URL查詢或簡單的URL反查。

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

  • 在模板中:使用url模板標籤
  • 在Python程式碼中:使用django.core.urlesolvers.reverse()函式
  • 在更高層的與處理Django模型例項相關的程式碼中:使用get_absolute_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" %}

在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="new-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="{% ulr "news-year-archive" yearvar%}">{{ yearvar }} Archive</a>
</li>
{% endfor %}
</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】。