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

全國咨詢/投訴熱線:400-618-4000

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

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

一、urls硬編碼

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

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

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

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

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

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

二、URL的反向解析

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

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

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

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

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

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

對于不同層級,Django提供不同的工具用于URL 反查:

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

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

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


1、命名空間:

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

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

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

<2>實例命名空間:

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

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

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

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

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

解決方案為:

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

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

三、url反向解析實例

在我們的django項目中通常App,目錄結(jié)構(gòu)就可以如下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.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')),
]

根據(jù)路由分發(fā)到各個相應(yīng)的app中。并添加實例命名空間


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)的時候,都能自動生成。而如果使用硬鏈接硬編碼,就只能在views.py和靜態(tài)文件中逐個修改url地址,不僅耗費時間,更容易產(chǎn)生錯誤。

0 分享到:
和我們在線交談!