教育行業(yè)A股IPO第一股(股票代碼 003032)

全國(guó)咨詢/投訴熱線:400-618-4000

Django之URL反向解析介紹[傳智播客]

更新時(shí)間:2019年10月15日17時(shí)07分 來源:傳智播客 瀏覽次數(shù):

一、urls硬編碼

在反向解析和命名空間之前我們先來說說URLS硬編碼,用django開發(fā)應(yīng)?的時(shí)候,可以完全是在urls.py中硬編碼配置地址,在views.py中HttpResponseRedirect()也是硬編碼轉(zhuǎn)向地址,當(dāng)然在template中也是一樣了,這樣帶來一個(gè)問題,如果在urls.py中修改了某個(gè)頁面的地址(也就是說更改路由系統(tǒng)中對(duì)應(yīng)的路由分發(fā)),那么所有的地方(views.py和template中)都要修改。問題出在硬編碼,緊耦合使得在大量的模板中修改URLS成為富有挑戰(zhàn)性的項(xiàng)目。來看下面的模板文件index.html中,我們到的鏈接硬編碼成這樣:

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

如果使用軟編碼之后,無論怎么更改路由系統(tǒng)中的路由分發(fā),只有對(duì)應(yīng)的namespace與name屬性值不變,就不必修改在views.py和template中的url,也就是說

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

在templates中更改為軟編碼之后,其實(shí)在templates,index.html文件生成的時(shí)候,仍然是

<li><a href="/goods/index/">url軟編碼</a></li>
Django之URL反向解析

二、URL的反向解析

在使用Django項(xiàng)目時(shí),一個(gè)常見的需求是獲得URL的最終形式,以用于嵌入到生成的內(nèi)容中(視圖中和顯示給用戶的URL等)或者用于處理服務(wù)器端的導(dǎo)航(重定向等)。 人們強(qiáng)烈希望不要硬編碼這些URL(費(fèi)力、不可擴(kuò)展且容易產(chǎn)生錯(cuò)誤)或者設(shè)計(jì)一種與URLconf毫不相關(guān)的專門的URL生成機(jī)制,因?yàn)檫@樣容易導(dǎo)致一定程度上產(chǎn)生過期的URL?!就扑]了解:python+人工智能課程

獲取一個(gè)URL最開始想到的信息是處理它視圖的標(biāo)識(shí)(例如名字),查找正確的URL的其它必要的信息有視圖參數(shù)的類型(位置參數(shù)、關(guān)鍵字參數(shù))和值。Django提供一個(gè)辦法是讓URL映射是URL設(shè)計(jì)唯一的地方。你填充你的URLconf,然后可以雙向使用它:

(1)根據(jù)用戶/瀏覽器?發(fā)起的URL 請(qǐng)求,它調(diào)?用正確的Django 視圖,并從URL 中提取它的參數(shù)需要的值。

(2)根據(jù)Django視圖的標(biāo)識(shí)和將要傳遞給它的參數(shù)的值,獲取與之關(guān)聯(lián)的URL。

第一種方式是我們常說的根據(jù)地址定位URL。

第二種方式叫做反向解析URL、反向URL 匹配、反向URL查詢或者簡(jiǎn)單的URL反查。在需要URL的地方。

對(duì)于不同層級(jí),Django提供不同的工具用于URL 反查:

(1)在模板中:使?用url模板標(biāo)簽。

(2)在Python代碼中:使?django.core.urlresolvers.reverse() 函數(shù)。

(3)在更高層的與處理Django模型實(shí)例相關(guān)的代碼中:使用get_absolute_url()方法。


1、命名空間:

URL命名空間允許你反查到唯一的命名URL模式,即使不同的應(yīng)用使用相同的URL 名稱。第三方應(yīng)用始終使用帶命名空間的URL 是一個(gè)很好的實(shí)踐。類似地,它還允許你在一個(gè)應(yīng)用有多個(gè)實(shí)例部署的情況下反查URL。換句話講,因?yàn)橐粋€(gè)應(yīng)用的多個(gè)實(shí)例共享相同的命名URL,命名空間將提供一種區(qū)分這些命名URL 的方法。一個(gè)URL命名空間有兩個(gè)部分,它們都是字符串:

<1>應(yīng)用命名空間:

它表示正在部署的應(yīng)用的名稱。一個(gè)應(yīng)用的每個(gè)實(shí)例例具有相同的應(yīng)用命名空間。例如,可以預(yù)見Django的管理站點(diǎn)的應(yīng)?命名空間是'admin '。

<2>實(shí)例命名空間:

它表示應(yīng)用的一個(gè)特定的實(shí)例。實(shí)例的命名空間在你的全部項(xiàng)目中應(yīng)該是唯一的。但是,一個(gè)實(shí)例的命名空間可以和應(yīng)用的命名空間相同。它用于表示一個(gè)應(yīng)用的默認(rèn)實(shí)例。例如,Django管理站點(diǎn)實(shí)例具有一個(gè)默認(rèn)的實(shí)例命名空間'admin'。URL的命名空間使用':'操作符指定。例如,管理站點(diǎn)應(yīng)用的主頁使用'admin:index'。它表示'admin'的一個(gè)命名空間和'index'的一個(gè)命名URL。

# include函數(shù)的API
include(arg, namespace=None, app_name=None)
# namespace設(shè)置實(shí)例例命名空間,app_name設(shè)置應(yīng)?用命名空間
# 不不能只設(shè)置app_name,否則會(huì)報(bào)錯(cuò),以下是報(bào)錯(cuò)的源碼
if app_name and not namespace:
raise ValueError('Must specify a namespace if specifying app_name.')

一般來說,同一應(yīng)用下的不同實(shí)例應(yīng)該具有相同的應(yīng)用命名空間,但是,這并不意味著不同應(yīng)用可以使用相同的實(shí)例命名空間,因?yàn)閷?shí)例命名空間在你所有項(xiàng)目中都是唯一的。

問題: 另外在添加命名空間 namespace時(shí)可能會(huì)出現(xiàn)以下這個(gè)問題:

'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.

解決方案為:

在對(duì)應(yīng)的app應(yīng)用的urls.py中添加app_name = '[應(yīng)用名稱]'如下

from django.conf.urls import url
from . import views
app_name = 'users'
# users為當(dāng)前應(yīng)?用的名稱
urlpatterns = [
url('^$', views.index),
url('^(\d+)/$', views.detail),
]

三、url反向解析實(shí)例

在我們的django項(xiàng)目中通常App,目錄結(jié)構(gòu)就可以如下daily_fresh_demo

daily_fresh_demo 
 |----daily_fresh_demo
    |----__init__.py
    |----settings.py
    |----urls.py
    |----wsgi.py
  |----df_cart #對(duì)商品購(gòu)物?車管理理
|---- migrations # 遷移?文件?目錄
|---- admin.py
|---- apps.py
|---- models.py
|---- test.py
|---- urls.py
|---- views.py
|---- __init__.py
  |----df_goods  #商品以及后臺(tái)管理理
...
  |----df_user #?用戶管理理
...
  |----df_order #訂單管理理
...
  |----templates
     |index.html

1、路由分發(fā):

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')), # 添
加實(shí)例例命名空間
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ā)到各個(gè)相應(yīng)的app中。并添加實(shí)例命名空間


2、子路由

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

df_goods中的路由,添加應(yīng)?命名空間。并在url函數(shù)中添加name屬性。

3、視圖函數(shù)

daily_fresh_demo/df_goods/views.py
from django.shortcuts import render, reverse
def index(request):
print(reverse("df_goods:index")) # 利利?用reverse函數(shù)反向解析url
  # 打印結(jié)果為/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、結(jié)果

靜態(tài)文件中index.html的url解析結(jié)果如下

<!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> # 軟編碼通過解析后得到的結(jié)果與硬編碼?一致
</body>
</html>

總結(jié):這樣一來通過命名空間,無論在templates文件中有多龐大的url地址映射,只要使用url軟編碼,在更改路由系統(tǒng)的時(shí)候,都能自動(dòng)生成。而如果使用硬鏈接硬編碼,就只能在views.py和靜態(tài)文件中逐個(gè)修改url地址,不僅耗費(fèi)時(shí)間,更容易產(chǎn)生錯(cuò)誤。

0 分享到:
和我們?cè)诰€交談!