django反向解析URL和URL命名空間 首先明確幾個概念: 1.在html頁面上的內容特別是向用戶展示的url地址,比如常見的超鏈接,圖片鏈接等,最好能動態生成,而不要固定. 2.一個django項目中一般包含了多個django應用(app). 3.一個視圖(view)往往對應多個url地址. ...
django反向解析URL和URL命名空間
首先明確幾個概念:
1.在html頁面上的內容特別是向用戶展示的url地址,比如常見的超鏈接,圖片鏈接等,最好能動態生成,而不要固定.
2.一個django項目中一般包含了多個django應用(app).
3.一個視圖(view)往往對應多個url地址.
在django中實現反向解析URL必備條件就是url和view能一對一的匹配.
(通過view找到唯一一個對應的url,通過url也能找到唯一一個view)
最簡單的方式就是使用name
,可以理解為url起了一個名字.
例如:
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]
此時的news-year-archive
就可以表示/articles/nnnn/
在view中進行使用.
在templates中使用
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
在view中使用
from django.urls import reverse
from django.http import HttpResponseRedirect
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
但是使用name
也存在一定的問題,比如在同一個項目中的不同的app中name
可能會重名(導致反解析時一個view對應多個url),而且給每一個url起不同名字也很繁瑣.
這時候就會用到URL命名空間
URL命名空間包括兩個部分:app_name
(應用命名空間)以及namespace
(實例命名空間)
對於app_name
官方解釋"它表示正在部署的應用的名稱。一個應用的每個實例具有相同的應用命名空間。",比較好理解.
也就是說可以通過設置app_name
來區分不同app中同名的name
了,使用:
連接.
但是對於namespace
官方解釋"它表示應用的一個特定的實例。實例的命名空間在你的全部項目中應該是唯一的。但是,一個實例的命名空間可以和應用的命名空間相同。",就比較的難以理解.
namespace
主要功能為了區分同一個app下不同實例,使得反解析url時能獲得正確的結果.
例如:
在不加入namespace
時,
訪問http://127.0.0.1:8000/ccc/aaa/
和http://127.0.0.1:8000/bbb/aaa/
結果均為/ccc/aaa/
,這顯然不是我們想要獲取的結果.
# 主url.py
urlpatterns = [
...
url(r'^bbb/', include("test_namespace2.urls")),
url(r'^ccc/', include("test_namespace2.urls")),
...
]
# test_namespace2/url.py
app_name = "app02"
urlpatterns = [
url(r'aaa/$', views.aaa, name="index"),
]
# test_namespace2/view.py
def aaa(request):
return HttpResponse(reverse("app02:index"))
做出一些修改,加入namespace
用作區別
# 主url.py
urlpatterns = [
...
url(r'^bbb/', include("test_namespace2.urls", namespace='bbb')), # 加入了namespace
url(r'^ccc/', include("test_namespace2.urls", namespace='ccc')),
...
]
# test_namespace2/view.py
def aaa(request):
return HttpResponse(reverse("app02:index", current_app=request.resolver_match.namespace)) # 使用namespace
這樣就會獲得正確的結果了.
使用方式:
首先在,主url.py中添加namespace
urlpatterns = [
url(r'^polls/', include('polls.urls',namespace='test')),
]
然後要在app的urls.py中添加app_name
和name
比如:
app_name = 'polls'
urlpatterns = [
#...
url(r'^$', views.index, name='index'),
#...
然後在view和templates中使用了,此時就算有多個app中都有名為index
的name
也不會有問題了
使用方式,使用形如app_name:name
在view中使用:
reverse('polls:index', current_app=request.resolver_match.namespace)
在templates中使用
{% url 'polls:index' %}