目錄
一、 URL name詳解
向視圖傳遞額外的參數
利用reverse函數反向生成URL
對有參數的url設定name
二、include路由轉發
傳遞額外的參數給include()
三、URL命名空間
四、include()本質
一、 URL name詳解
from django.conf.urls import url
from django.contrib import admin
from calc import views as calc_views
urlpatterns = [
url(r'^add/$', calc_views.add, name='add'),
url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
url(r'^admin/', admin.site.urls),
]
url(r'^add/$', calc_views.add, name='add'), 這裡的 name='add' 是用來幹什麼的呢?
簡單說,name 可以用于在 templates, models, views ……中得到對應的網址,相當于“給網址取了個名字”,隻要這個名字不變,網址變了也能通過名字擷取到。
模闆中可以這樣利用name
不帶參數的:
{% url 'name' %}
帶參數的:參數可以是變量名
{% url 'name' 參數 %}
結合上面的urls.py
不帶參數:
<a href="{% url 'add' %}">添加</a>
上面模闆經過渲染後的标簽是這樣的:
<a href="/add/">添加</a>
帶參數的:
<a href="{% url 'add2' 4 5 %}">link</a>
經過渲染後:
<a href="/add/4/5/">link</a>
當 urls.py 進行更改,前提是不改 name(這個參數設定好後不要輕易改),擷取的網址也會動态地跟着變,比如改成:
url(r'^new_add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
注意: add 變成了 new_add,但是後面的沒改,這時
name='add2'
就會渲染對應的網址成
{% url 'add2' 4 5 %}
/new_add/4/5/
向視圖傳遞額外的參數
url()中允許你傳遞一個Python字典作為額外的關鍵字參數給視圖函數。
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
在上面的例子中,對于/blog/2005/請求,Django将調用views.year_archive(request, year='2005', foo='bar')。
注意:命名關鍵字參數和在字典中傳遞的額外參數要避免重名。
利用reverse函數反向生成URL
urls.py
from app01 import views as views
urlpatterns = [
url(r'^login/',views.login),
url(r'^index/first/',views.index,name='first'),
]
views.py
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def login(request):
url = reverse('first')
print(url) # 列印結果:/index/first/
return redirect(url)
def index(request):
return HttpResponse('index/first')
對有參數的url設定name
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]
模闆代碼中使用:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> # 注意模版語言的用法,注意參數的傳遞方法
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
views.py視圖函數:
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,)))
二、include路由轉發
通常,我們會在每個app裡,各自建立一個urls.py路由子產品,然後從根路由出發,将app所屬的url請求,全部轉發到相應的urls.py子產品中。
建立兩個app:cmdb和openstack,并分别在這兩個app目錄下建立urls.py檔案
from django.conf.urls import url,include
# 需要先導入include函數
from django.contrib import admin
from app01 import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^cmdb/',include('cmdb.urls')),
url(r'^openstack/',include('openstack.urls')),
]
傳遞額外的參數給include()
參數會傳遞給include指向的urlconf中的每一行,例如,下面兩種URLconf配置方式在功能上完全相同:
配置一:
# main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^blog/', include('inner'), {'blogid': 3}),
]
# inner.py
from django.conf.urls import url
from mysite import views
urlpatterns = [
url(r'^archive/$', views.archive),
url(r'^about/$', views.about),
]
配置二:
# main.py
from django.conf.urls import include, url
from mysite import views
urlpatterns = [
url(r'^blog/', include('inner')),
]
# inner.py
from django.conf.urls import url
urlpatterns = [
url(r'^archive/$', views.archive, {'blogid': 3}),
url(r'^about/$', views.about, {'blogid': 3}),
]
注意,隻有當你确定被include的URLconf中的每個視圖都接收你傳遞給它們的額外的參數時才有意義,否則其中一個以上視圖不接收該參數都将導緻錯誤異常。
三、URL命名空間
URL命名空間可以保證反查到唯一的URL。
from django.conf.urls import url,include
urlpatterns = [
url(r'^cmdb/',include('cmdb.urls',namespace='cmdb')),
url(r'^openstack/',include('openstack.urls',namespace='openstack')),
]
cmdb/urls.py
from django.conf.urls import url
from cmdb import views
urlpatterns = [
url(r'host/',views.host,name='host'),
]
在模闆中使用:
<a href="{% url 'cmdb:host' %}">跳轉</a>
在視圖中利用reverse()函數反向生成url
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def host(request):
url = reverse('cmdb:host')
print(url) # 列印結果:/cmdb/host/
return HttpResponse('cmdb.host')
注意:namespace與name在模闆檔案和視圖函數中使用的時候要用冒号分隔,如:“cmdb:host”
四、include()本質
include()函數實際上就是傳回一個元組:
([], None, None)
第一個元素可以是一個清單,清單中盛放url()子路由配置;
第二個元素是app_name,可以為None;
第三個元素是namespace,需要反向生成url時,可根據需求填寫;
是以urls.py也可以這樣寫:
from django.conf.urls import url
urlpatterns = [
url(r'^openstack/',([],None,None,),
]
直接用一個元組替代include()
如下,直接進行子路由分發:
from django.conf.urls import url,include
from cmdb import views as cviews
from app01 import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^index/',views.index,name='index'),
url(r'^cmdb/',include('cmdb.urls',namespace='cmdb')),
# url(r'^openstack/',include('openstack.urls',namespace='openstack')),
url(r'^openstack/',([
url(r'^host/',cviews.host,name='host'),
url(r'^host/add/',cviews.addhost,name='addhost'),
url(r'^host/(\d+)/change',cviews.changehost,name='changehost'),
],None,'openstack')),
]
以上元組中的'openstack',就相當于include()函數的 namespace='openstack'
。