Django之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。

urls.py

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'



作者:天佑俊辰
鏈接:https://www.jianshu.com/p/0e5bdc73fcab
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM