django-url調度器-中級篇

来源:http://www.cnblogs.com/scolia/archive/2016/06/06/5564622.html
-Advertisement-
Play Games

在初級篇中,我們接觸了: 1.url 的簡單編寫 2.兩種傳參的方式 3.捕獲的參數總是字元串 4.為視圖設置預設參數 …… 在中級篇中將更進一步。 包含其它的URLconfs 當網站非常大的時候,將所有的url都寫在一個url模塊中會非常的臃腫,且後期不便於維護。此時,就可以使用包含的方式將部分的 ...


  在初級篇中,我們接觸了:

  1.url 的簡單編寫

  2.兩種傳參的方式

  3.捕獲的參數總是字元串

  4.為視圖設置預設參數

  ……

  在中級篇中將更進一步。

包含其它的URLconfs

  當網站非常大的時候,將所有的url都寫在一個url模塊中會非常的臃腫,且後期不便於維護。此時,就可以使用包含的方式將部分的url放在另一個url模塊中。最常見的就是每個app的url都進行分離。

官方代碼示例:

from django.conf.urls import include, url
urlpatterns = [
    # ... snip ...
    url(r'^community/', include('django_website.aggregator.urls')),
    url(r'^contact/', include('django_website.contact.urls')),
    # ... snip ...]

 

  註意,這個例子中的正則表達式沒有包含$(字元串結束匹配符),但是包含一個末尾的斜杠。每當 Django 遇到 include()(django.conf.urls.include())時,它會去掉 URL 中匹配的部分並將剩下的字元串發送給包含的 URLconf 做進一步處理

  另外一種包含其它URL 模式的方式是使用一個url() 實例的列表。例如,請看下麵的URLconf:

from django.conf.urls import include, url
from apps.main import views as main_viewsfrom credit import views as credit_views
extra_patterns = [
    url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
    url(r'^charge/$', credit_views.charge),
] urlpatterns
= [ url(r'^$', main_views.homepage), url(r'^help/', include('apps.help.urls')), url(r'^credit/', include(extra_patterns)),
]

  在這個例子中,/credit/reports/ URL 將被 credit.views.report() 這個Django 視圖處理。

  這種方法可以用來去除 URLconf 中的冗餘,其中某個模式首碼被重覆使用。例如,考慮這個 URLconf:

from django.conf.urls import urlfrom . import views
urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]

  我們可以改進它,通過只聲明共同的路徑首碼一次並將後面的部分分組:

from django.conf.urls import include, urlfrom . import views
urlpatterns = [
    url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
        url(r'^history/$', views.history),
        url(r'^edit/$', views.edit),
        url(r'^discuss/$', views.discuss),
        url(r'^permissions/$', views.permissions),
    ])),
]

 

  下麵,我們總結一下使用 include 能達到什麼效果:

  1.分離 url ,例如將 app 相關的 url 都移到對應的 app 目錄下,這樣邏輯更清晰,也更易維護。

  2.去除 url 中的冗餘。

  當然,還有更高級的用法,例如:命名空間,反向解析等。這些等到高級篇再進行討論。

 


 

包含之後的參數傳遞

  包含的 URLconf 會收到來自父URLconf 捕獲的任何參數(也就是說捕獲到的參數是向下傳遞的),所以下麵的例子是合法的:

# In settings/urls/main.py
from django.conf.urls import include, url
urlpatterns = [
    url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
]

# In foo/urls/blog.py
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.blog.index),
    url(r'^archive/$', views.blog.archive),
]

 

  在上面的例子中,捕獲的 "username" 變數將被如期傳遞給 include() 指向的 URLconf。

 


 

 嵌套的參數

  正則表達式允許嵌套參數,Django 將解析它們並傳遞給視圖。當反查時,Django 將嘗試填滿所有外圍捕獲的參數,並忽略嵌套捕獲的參數。

  例如下麵的 URL 模式,它帶有一個可選的 page 參數:

from django.conf.urls import url
urlpatterns = [
    url(r'blog/(page-(\d+)/)?$', blog_articles),                  # bad
    url(r'comments/(?:page-(?P<page_number>\d+)/)?$', comments),  # good
]

  兩個模式都使用嵌套的參數,其解析方式是:例如 blog/page-2/ 將匹配 blog_articles 並帶有兩個位置參數 page-2/ 和 2。(也就是凡是分組都會傳遞參數,順序由內層到外層)

  而在正在表達式中 (?:....)雖然類似一個分組,但並不是分組。

  所以,第二個 comments 的模式將匹配 comments/page-2/ 並帶有一個值為 2 的關鍵字參數 page_number。這個例子中外圍參數是一個不捕獲的參數(?:...)。

  blog_articles 視圖需要最外層捕獲的參數來反查,在這個例子中是 page-2/ 或者沒有參數,而 comments 可以不帶參數或者用一個 page_number 值來反查。

  嵌套捕獲的參數使得視圖參數和URL 之間存在強耦合,正如 blog_articles 所示:視圖接收URL(page-2/)的一部分,而不只是視圖所要的值(通常我只需要知道一個頁碼,也就是這裡的 2 就行了)。這種耦合在反查時更加顯著,因為反查視圖時我們需要傳遞 URL 的一個片段而不只是 page 的值。

  總結:儘量不要捕獲不需要的參數,因為這樣不僅在函數中需要額外的處理,而且在進行各種反向查詢的時候也會困難些。

 


 

傳遞額外的選項給視圖函數

  URLconfs 具有一個鉤子,讓你傳遞一個Python 字典作為額外的參數傳遞給視圖函數。

  django.conf.urls.url() 函數可以接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。

例如:

from django.conf.urls import urlfrom . 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')。

  但是這樣會出現一定的衝突,當 URL 模式捕獲的命名關鍵字參數和在字典中傳遞的額外參數具有相同的名稱時,將使用字典中的參數而不是URL 中捕獲的參數。(也就是說字典中的參數優先順序更高。

 


 

傳遞額外的選項給include

  類似地,你可以傳遞額外的選項給include()。當你傳遞額外的選項給include() 時,被包含的URLconf 的每一行將被傳遞這些額外的選項。

  也就是說在 include 中傳遞的額外參數將傳給所有被包含的 url

設置一:
# main.py
from django.conf.urls import include, url
urlpatterns = [
    url(r'^blog/', include('inner'), {'blogid': 3}),
]
# inner.pyfrom django.conf.urls import urlfrom mysite import views urlpatterns = [ url(r'^archive/$', views.archive), url(r'^about/$', views.about),
] 設置二:
# main.py from django.conf.urls import include, urlfrom mysite import views urlpatterns = [ url(r'^blog/', include('inner')),
]
# inner.pyfrom django.conf.urls import url urlpatterns = [ url(r'^archive/$', views.archive, {'blogid': 3}), url(r'^about/$', views.about, {'blogid': 3})
,]

 

  但是,如果你不確定你的所有的相關視圖函數都需要這個額外的參數的話,將會導致參數傳遞錯誤,例如多傳了參數。而發生這種情況時,毫無疑問會發生報錯。所以在使用這個功能的時候要足夠的謹慎。你要知道你做了什麼。

 


URL 的反向解析

  反向解析是做什麼的?反向解析,就是在模板中,或 views 函數中進行 url 的獲取或者重定向到指定頁面的時候,可以更加靈活的寫入目標 url 而不用硬編碼。

  例如,在沒有使用反向解析之前:

<a href="/xxx/xxx/">測試</a>        #模板中

def xxx(request):        #視圖函數需要重定向時
        .....
    return HttpResponseRedirect('/xxx/xxx/') 

  如果此時處於業務需要,想要改動 url 時,那麼代碼中所以用到的地方就都需要改。如果此時用的這個 url 的地方有 N 個,就意味著要改動 N 次。此時,你可能想死的心都有了。為了延長程式員的壽命,反向解析就顯得非常重要了。

  Django 通過為指定的url命名的方式,來代替硬編碼,而為瞭解決命名重覆的問題,又引入了命名空間,下麵逐一介紹。

例子:  

from django.conf.urls import url
from . import views
urlpatterns = [
    #...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...]

  在這裡,添加了 name 這個屬性,並將其賦值為'news-year-archive'。這就是為這個 url 進行了命名。

  在進行命名了以後,就可以這樣寫:

<a href="{% url ‘new-year-archive’}>測試</a>        #模板中

from django.core.urlresolvers import reverse
def xxx(request):        #視圖函數
    ......
    return HttpResponseRedirect(reverse('news-year-archive',)) 

  這裡的reverse()函數的作用是進行反向解析,以直接訪問其他視圖函數。

  下麵來分析一下這個函數要怎麼用:

 reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None) 

  這裡接收 5 個參數,下麵來看看這些參數都是做什麼的:

  viewname:是一個字元串,可以是一個Python路徑視圖對象(廢棄),一個URL模式名稱( reverse('news_archive') ),或可調用視圖對象( from news import views /reverse(views.archive) )。

  urlconf : reverse 在其內部是這樣處理的: if urlconf is None: urlconf = get_urlconf() ,那我們去看看get_urlconf()是做什麼的。這時,我們看到這樣的一句說明:

def get_urlconf(default=None):
    """
    Returns the root URLconf to use for the current thread if it has been
    changed from the default one.
    """
    return getattr(_urlconfs, "value", default)

  返回根 url 模塊的。

  也就是說這個屬性決定此次反向解析使用哪個 url 模塊。預設是當前的根 url 模塊

  args : 用於傳參,也就是說方向解析到指定的 view 函數後,並傳遞了參數,可以是元組或列表,表示按照順序進行位置傳參。

  kwargs:也是用於傳參的,不同的是,這裡是一個字典,傳參時使用關鍵字傳參的方式。

  current_app :參數允許您提供一個提示解析器指示應用程式當前執行的視圖所屬(所在app)。這個current_app參數作為一個提示,根據名稱空間URL解決策略,來解決應用程式名稱空間URL在特定的應用程式實例。

  註意:

    若沒有找到匹配的對象,則拋出 NoReverseMatch 異常。

    一般而言幾乎所有的正則都能逆向解析,但是目前並不能匹配含有選擇符(|)的正則。除此之外幾乎可以很輕鬆得逆向解析,但這種逆向解析是不可逆的。

    反向解析Python路徑的能力,如反向(“news.views.archive”),已被棄用。(在1.8中)

 

官方手冊例子:

from django.conf.urls import url
from . import views

urlpatterns = [
    #...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...
]

 

  根據這裡的設計,某一年nnnn對應的歸檔的URL是/articles/nnnn/

  你可以在模板的代碼中使用下麵的方法獲得它們:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

    傳遞多個參數時用空格隔開: 

{% url 'add' 123 321  %}
{% url 'add' num1=123 num2=321  %}

  在Python 代碼中,這樣使用:

rom django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

  如果出於某種原因決定按年歸檔文章發佈的URL應該調整一下,那麼你將只需要修改URLconf 中的內容。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先介紹下,目前C#作為一門快速開發的語言,在面試的過程中需要註意的技術知識點,瞭解下麵的知識點對於初級工程師入職非常有幫助,也是自己的親身體悟。 1. 簡述 private、 protected、 public、 internal 修飾符的訪問許可權。 答 . private : 私有成員, 在類的 ...
  • ...
  • 最近剛剛接觸MVC不久,因項目中要用到分頁,網上找了下資料,最後採用了MvcPager(http://www.webdiyer.com/),支持同步和Ajax非同步分頁。廢話不多說了直接上代碼。 一.MvcPager非同步 ViewModel: public class Article { [Displ ...
  • 使用DataSet可以直接輸出XML,並可指定是否帶有Schema: 不過,這樣將不會輸出值為Null的欄位,如: 你可能希望結果是這樣: 但結果為: c沒有輸出在XML文件中,其實我覺得這樣更合理,否則,如何區分null和""呢?如果希望輸出c,那隻能通過XmlDocument自己寫了: 空節點顯 ...
  • WPF綁定數據 模型類(繼承 INotifyPropertyChanged,實現屬性的變更通知) 最後的實現效果: 方法一:前臺頁面不對數據做綁定,後臺對RadGridView控制項做數據綁定 方法二:前端頁面做 ItemsSource空綁定,後臺用DataContext綁定上下文數據 記錄完成。 ...
  • 在“如何用MediaCapture解決二維碼掃描問題”這篇文章中,我們通過“成像”、“截圖”與“識別”三個步驟介紹了使用MediaCapture掃碼的主要過程及註意事項。本文主要針對“識別”的過程,對Barcode的概念作出一個較為簡單的介紹,同時也會討論ZXing的使用方法。 ZXing是一個Ja ...
  • 在WEB系統中,列印的確是比較煩人的問題,如果我們能製作一個屬於自己的自定義的列印插件,那麼我們在後續自定義列印的時候能隨心所欲的控制列印,這樣的效果對於程式員來說是非常開心的一件事件,本文將自己開發編寫的C# 製作的HTML列印插件分享出來,讓有同樣需求的朋友提供一個參考;此插件是基於Micros ...
  • 基於Jenkins快速搭建持續集成環境.(Jenkins+tortoisesvn+MSBuild) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...