更新時間:2019年10月15日17時07分 來源:傳智播客 瀏覽次數(shù):
在反向解析和命名空間之前我們先來說說URLS硬編碼,用django開發(fā)應?的時候,可以完全是在urls.py中硬編碼配置地址,在views.py中HttpResponseRedirect()也是硬編碼轉向地址,當然在template中也是一樣了,這樣帶來一個問題,如果在urls.py中修改了某個頁面的地址(也就是說更改路由系統(tǒng)中對應的路由分發(fā)),那么所有的地方(views.py和template中)都要修改。問題出在硬編碼,緊耦合使得在大量的模板中修改URLS成為富有挑戰(zhàn)性的項目。來看下面的模板文件index.html中,我們到的鏈接硬編碼成這樣:
<li><a href="/goods/index/">url硬編碼</a></li>
如果使用軟編碼之后,無論怎么更改路由系統(tǒng)中的路由分發(fā),只有對應的namespace與name屬性值不變,就不必修改在views.py和template中的url,也就是說
在使用Django項目時,一個常見的需求是獲得URL的最終形式,以用于嵌入到生成的內(nèi)容中(視圖中和顯示給用戶的URL等)或者用于處理服務器端的導航(重定向等)。 人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產(chǎn)生錯誤)或者設計一種與URLconf毫不相關的專門的URL生成機制,因為這樣容易導致一定程度上產(chǎn)生過期的URL?!就扑]了解:python+人工智能課程】
獲取一個URL最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL的其它必要的信息有視圖參數(shù)的類型(位置參數(shù)、關鍵字參數(shù))和值。Django提供一個辦法是讓URL映射是URL設計唯一的地方。你填充你的URLconf,然后可以雙向使用它:
(1)根據(jù)用戶/瀏覽器?發(fā)起的URL 請求,它調(diào)?用正確的Django 視圖,并從URL 中提取它的參數(shù)需要的值。
(2)根據(jù)Django視圖的標識和將要傳遞給它的參數(shù)的值,獲取與之關聯(lián)的URL。
第一種方式是我們常說的根據(jù)地址定位URL。
第二種方式叫做反向解析URL、反向URL 匹配、反向URL查詢或者簡單的URL反查。在需要URL的地方。
對于不同層級,Django提供不同的工具用于URL 反查:
(1)在模板中:使?用url模板標簽。
(2)在Python代碼中:使?django.core.urlresolvers.reverse() 函數(shù)。
(3)在更高層的與處理Django模型實例相關的代碼中:使用get_absolute_url()方法。
1、命名空間:
URL命名空間允許你反查到唯一的命名URL模式,即使不同的應用使用相同的URL 名稱。第三方應用始終使用帶命名空間的URL 是一個很好的實踐。類似地,它還允許你在一個應用有多個實例部署的情況下反查URL。換句話講,因為一個應用的多個實例共享相同的命名URL,命名空間將提供一種區(qū)分這些命名URL 的方法。一個URL命名空間有兩個部分,它們都是字符串:
<1>應用命名空間:
它表示正在部署的應用的名稱。一個應用的每個實例例具有相同的應用命名空間。例如,可以預見Django的管理站點的應?命名空間是'admin '。
<2>實例命名空間:
它表示應用的一個特定的實例。實例的命名空間在你的全部項目中應該是唯一的。但是,一個實例的命名空間可以和應用的命名空間相同。它用于表示一個應用的默認實例。例如,Django管理站點實例具有一個默認的實例命名空間'admin'。URL的命名空間使用':'操作符指定。例如,管理站點應用的主頁使用'admin:index'。它表示'admin'的一個命名空間和'index'的一個命名URL。
# include函數(shù)的APIinclude(arg, namespace=None, app_name=None)# namespace設置實例例命名空間,app_name設置應?用命名空間# 不不能只設置app_name,否則會報錯,以下是報錯的源碼if app_name and not namespace:raise ValueError('Must specify a namespace if specifying app_name.')
一般來說,同一應用下的不同實例應該具有相同的應用命名空間,但是,這并不意味著不同應用可以使用相同的實例命名空間,因為實例命名空間在你所有項目中都是唯一的。
問題: 另外在添加命名空間 namespace時可能會出現(xiàn)以下這個問題:
'Specifying a namespace in include() without providing an app_name 'django.core.exceptions.ImproperlyConfigured: Specifying a namespace ininclude() without providing an app_name is not supported. Set the app_nameattribute in the included module, or pass a 2-tuple containing the list of
patterns and app_name instead.
解決方案為:
在對應的app應用的urls.py中添加app_name = '[應用名稱]'如下
from django.conf.urls import urlfrom . import viewsapp_name = 'users'# users為當前應?用的名稱urlpatterns = [url('^$', views.index),url('^(\d+)/$', views.detail),]
三、url反向解析實例
在我們的django項目中通常App,目錄結構就可以如下daily_fresh_demo
daily_fresh_demo|----daily_fresh_demo|----__init__.py|----settings.py|----urls.py|----wsgi.py|----df_cart #對商品購物?車管理理|---- migrations # 遷移?文件?目錄|---- admin.py|---- apps.py|---- models.py|---- test.py|---- urls.py|---- views.py|---- __init__.py|----df_goods #商品以及后臺管理理...|----df_user #?用戶管理理...|----df_order #訂單管理理...|----templates|index.html
1、路由分發(fā):
daily_fresh_demo/daily_fresh_demo/urls.pyfrom django.contrib import adminfrom django.urls import path
from django.conf.urls import url, includeurlpatterns = [path('admin/', admin.site.urls),url(r'^goods/', include('df_goods.urls', namespace='df_goods')), # 添加實例例命名空間url(r'^user/', include('df_user.urls', namespace='df_user')),url(r'^cart/', include('df_cart.urls', namespace='df_cart')),url(r'^order/', include('df_order.urls', namespace='df_order')),]
根據(jù)路由分發(fā)到各個相應的app中。并添加實例命名空間
2、子路由
daily_fresh_demo/df_goods/urls.pyfrom django.conf.urls import urlfrom . import viewsapp_name = 'df_goods' # 應?用命名空間urlpatterns = [url('^index/$', views.index, name="index"),]
df_goods中的路由,添加應?命名空間。并在url函數(shù)中添加name屬性。
3、視圖函數(shù)
daily_fresh_demo/df_goods/views.pyfrom django.shortcuts import render, reversedef index(request):print(reverse("df_goods:index")) # 利利?用reverse函數(shù)反向解析url# 打印結果為/goods/index/return render(request, 'index.html')
4、靜態(tài)文件index.html
daily_fresh_demo/templates/index.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><a href="/goods/index">硬鏈接</a><a href="{% url "df_goods:index" %}">軟鏈接</a></body></html>
5、結果
靜態(tài)文件中index.html的url解析結果如下
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><a href="/goods/index">硬鏈接</a><a href="/goods/index/">軟鏈接</a> # 軟編碼通過解析后得到的結果與硬編碼?一致</body></html>
總結:這樣一來通過命名空間,無論在templates文件中有多龐大的url地址映射,只要使用url軟編碼,在更改路由系統(tǒng)的時候,都能自動生成。而如果使用硬鏈接硬編碼,就只能在views.py和靜態(tài)文件中逐個修改url地址,不僅耗費時間,更容易產(chǎn)生錯誤。