Django-url反向解析和命名空間

1、urls硬編碼

在反向解析和命名空間以前咱們先來講說URLS硬編碼,用django 開發應用的時候,能夠徹底是在urls.py 中硬編碼配置地址,在views.py中HttpResponseRedirect()也是硬編碼轉向地址,固然在template 中也是同樣了,這樣帶來一個問題,若是在urls.py 中修改了某個頁面的地址(也就是說更改路由系統中對應的路由分發),那麼全部的地方(views.py和template中)都要修改。問題出在硬編碼,緊耦合使得在大量的模板中修改 URLs 成爲富有挑戰性的項目。來看下面的模板文件index.html中,咱們到的連接硬編碼成這樣子:html

<li><a href="/goods/index/">url硬編碼</a></li>

若是使用軟編碼以後,不管怎麼更改路由系統中的路由分發,只有對應的namespace與name屬性值不變,就沒必要修改在views.py和template中的url,也就是說django

<li><a href="{% url "good:index" %}">url軟編碼</a></li>

在templates中更改成軟編碼以後,其實在templates,index.html文件生成的時候,仍然是瀏覽器

<li><a href="/goods/index/">url軟編碼</a></li>

 

2、URL的反向解析

在使用Django 項目時,一個常見的需求是得到URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。
人們強烈但願不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 絕不相關的專門的URL 生成機制,由於這樣容易致使必定程度上產生過時的URL。 服務器

獲取一個URL 最開始想到的信息是處理它視圖的標識(例如名字),查找正確的URL 的其它必要的信息有視圖參數的類型(位置參數、關鍵字參數)和值。
Django 提供一個辦法是讓URL 映射是URL 設計惟一的地方。你填充你的URLconf,而後能夠雙向使用它:
一、根據用戶/瀏覽器發起的URL 請求,它調用正確的Django 視圖,並從URL 中提取它的參數須要的值。
二、根據Django 視圖的標識和將要傳遞給它的參數的值,獲取與之關聯的URL。app

第一種方式是咱們常說的根據地址定位URL。函數

第二種方式叫作反向解析URL、反向URL 匹配、反向URL 查詢或者簡單的URL 反查工具

在須要URL 的地方,對於不一樣層級,Django 提供不一樣的工具用於URL 反查:
一、在模板中:使用url 模板標籤。
二、在Python 代碼中:使用 django.core.urlresolvers.reverse() 函數。
三、在更高層的與處理Django 模型實例相關的代碼中:使用 get_absolute_url() 方法。

編碼

一、命名空間:

URL 命名空間容許你反查到惟一的命名URL 模式,即便不一樣的應用使用相同的URL 名稱。第三方應用始終使用帶命名空間的URL 是一個很好的實踐。相似地,它還容許你在一個應用有多個實例部署的狀況下反查URL。換句話講,由於一個應用的多個實例共享相同的命名URL,命名空間將提供一種區分這些命名URL 的方法。url

一個URL 命名空間有兩個部分,它們都是字符串:spa

<1>、應用命名空間:

它表示正在部署的應用的名稱。一個應用的每一個實例具備相同的應用命名空間。例如,能夠預見Django 的管理站點的應用命名空間是' admin '。

<2>、實例命名空間:

它表示應用的一個特定的實例。實例的命名空間在你的所有項目中應該是惟一的。可是,一個實例的命名空間能夠和應用的命名空間相同。它用於表示一個應用的默認實例。例如,Django 管理站點實例具備一個默認的實例命名空間'admin'。 URL的命名空間使用':' 操做符指定。例如,管理站點應用的主頁使用' admin:index '。它表示' admin ' 的一個命名空間和' index ' 的一個命名URL.

# include函數的API include(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時可能會出現如下這個問題:

'Specifying a namespace in include() without providing an app_name ' django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute 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 url from . import views app_name = 'users'
# users爲當前應用的名稱
 urlpatterns = [ url('^$', views.index), url('^(\d+)/$', views.detail), ]

3、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

 

一、路由分發:

 
 
daily_fresh_demo/daily_fresh_demo/urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include urlpatterns = [ 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')),
]

根據路由分發到各個相應的app中。並添加實例命名空間

 

二、子路由

 
 
daily_fresh_demo/df_goods/urls.py

from
django.conf.urls import url from . import views app_name = 'df_goods' # 應用命名空間 urlpatterns = [ url('^index/$', views.index, name="index"), ]

df_goods中的路由,添加應用命名空間。並在url函數中添加name屬性。

三、視圖函數

daily_fresh_demo/df_goods/views.py from django.shortcuts import render, reverse def index(request): print(reverse("df_goods:index"))  # 利用reverse函數反向解析url
  # 打印結果爲/goods/index/
return render(request, 'index.html')

四、靜態文件 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>

五、結果

靜態文件中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軟編碼,在更改路由系統的時候,都能自動生成。而若是使用硬連接硬編碼 ,就只能在views.py和靜態文件中逐個修改url地址,不只耗費時間,更容易產生錯誤。

相關文章
相關標籤/搜索