日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

中國最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2

django教程

Django 視圖和URL配置

閱讀 (2364)

前一章中,我們解釋了如何建立一個 Django 項目并啟動 Django 開發服務器。 在這一章,你將會學到用Django創建動態網頁的基本知識。

你的第一個基于Django的頁面: Hello World

正如我們的第一個目標,創建一個網頁,用來輸出這個著名的示例信息:

Hello world.

如果你曾經發布過Hello world頁面,但是沒有使用網頁框架,只是簡單的在hello.html文本文件中輸入Hello World,然后上傳到任意的一個網頁服務器上。 注意,在這個過程中,你已經說明了兩個關于這個網頁的關鍵信息: 它包括(字符串 "Hello world")和它的URL( http://www.example.com/hello.html , 如果你把文件放在子目錄,也可能是 http://www.example.com/files/hello.html)。

使用Django,你會用不同的方法來說明這兩件事 頁面的內容是靠view function(視圖函數) 來產生,URL定義在 URLconf 中。首先,我們先寫一個Hello World視圖函數。

第一份視圖:

在上一章使用django-admin.py startproject制作的mysite文件夾中,創建一個叫做views.py的空文件。這個Python模塊將包含這一章的視圖。 請留意,Django對于view.py的文件命名沒有特別的要求,它不在乎這個文件叫什么。但是根據約定,把它命名成view.py是個好主意,這樣有利于其他開發者讀懂你的代碼,正如你很容易的往下讀懂本文。

我們的Hello world視圖非常簡單。 這些是完整的函數和導入聲明,你需要輸入到views.py文件:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello world")

我們逐行逐句地分析一遍這段代碼:

首先,我們從 django.http 模塊導入(import) HttpResponse 類。參閱附錄 H 了解更多關于 HttpRequest和 HttpResponse 的細節。 我們需要導入這些類,因為我們會在后面用到。

接下來,我們定義一個叫做hello 的視圖函數。

每個視圖函數至少要有一個參數,通常被叫作request。 這是一個觸發這個視圖、包含當前Web請求信息的對象,是類django.http.HttpRequest的一個實例。在這個示例中,我們雖然不用request做任何事情,然而它仍必須是這個視圖的第一個參數。

注意視圖函數的名稱并不重要;并不一定非得以某種特定的方式命名才能讓 Django 識別它。 在這里我們把它命名為:hello,是因為這個名稱清晰的顯示了視圖的用意。同樣地,你可以用諸如:hello_wonderful_beautiful_world,這樣難看的短句來給它命名。 在下一小節(Your First URLconf),將告訴你Django是如何找到這個函數的。

這個函數只有簡單的一行代碼: 它僅僅返回一個HttpResponse對象,這個對象包含了文本“Hello world”。

這里主要講的是: 一個視圖就是Python的一個函數。這個函數第一個參數的類型是HttpRequest;它返回一個HttpResponse實例。為了使一個Python的函數成為一個Django可識別的視圖,它必須滿足這兩個條件。 (也有例外,但是我們稍后才會接觸到。

你的第一個URLconf

現在,如果你再運行:python manage.py runserver,你還將看到Django的歡迎頁面,而看不到我們剛才寫的Hello world顯示頁面。 那是因為我們的mysite項目還對hello視圖一無所知。我們需要通過一個詳細描述的URL來顯式的告訴它并且激活這個視圖。 (繼續我們剛才類似發布靜態HTML文件的例子。現在我們已經創建了HTML文件,但還沒有把它上傳至服務器的目錄。)為了綁定視圖函數和URL,我們使用URLconf。

URLconf 就像是 Django 所支撐網站的目錄。 它的本質是 URL 模式以及要為該 URL 模式調用的視圖函數之間的映射表。 你就是以這種方式告訴 Django,對于這個 URL 調用這段代碼,對于那個 URL 調用那段代碼。 例如,當用戶訪問/foo/時,調用視圖函數foo_view(),這個視圖函數存在于Python模塊文件view.py中。

前一章中執行 django-admin.py startproject 時,該腳本會自動為你建了一份 URLconf(即 urls.py 文件)。 默認的urls.py會像下面這個樣子:

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    # (r'^mysite/', include('mysite.foo.urls')),

    # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
    # to INSTALLED_APPS to enable admin documentation:
    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # (r'^admin/', include(admin.site.urls)),
)

默認的URLconf包含了一些被注釋起來的Django中常用的功能,僅僅只需去掉這些注釋就可以開啟這些功能. 下面是URLconf中忽略被注釋的行后的實際內容

from django.conf.urls.defaults import *

urlpatterns = patterns('',
)

讓我們逐行解釋一下代碼:

  • 第一行導入django.conf.urls.defaults下的所有模塊,它們是Django URLconf的基本構造。 這包含了一個patterns函數。
  • 第二行調用 patterns() 函數并將返回結果保存到 urlpatterns 變量。patterns函數當前只有一個參數—一個空的字符串。 (這個字符串可以被用來表示一個視圖函數的通用前綴。具體我們將在第八章里面介紹。)

當前應該注意是 urlpatterns 變量, Django 期望能從 ROOT_URLCONF 模塊中找到它。 該變量定義了 URL 以及用于處理這些 URL 的代碼之間的映射關系。 默認情況下,URLconf 所有內容都被注釋起來了——Django 應用程序還是白版一塊。 (注:那是上一節中Django怎么知道顯示歡迎頁面的原因。 如果 URLconf 為空,Django 會認定你才創建好新項目,因此也就顯示那種信息。

如果想在URLconf中加入URL和view,只需增加映射URL模式和view功能的Python tuple即可. 這里演示如何添加view中hello功能.

from django.conf.urls.defaults import *
from mysite.views import hello

urlpatterns = patterns('',
    ('^hello/$', hello),
)

請留意:為了簡潔,我們移除了注釋代碼。 如果你喜歡的話,你可以保留那些行。)

我們做了兩處修改。

  • 首先,我們從模塊 (在 Python 的 import 語法中, mysite/views.py 轉譯為 mysite.views ) 中引入了hello 視圖。 (這假設mysite/views.py在你的Python搜索路徑上。關于搜索路徑的解釋,請參照下文。)
  • 接下來,我們為urlpatterns加上一行: (‘^hello/$’, hello), 這行被稱作URLpattern,它是一個Python的元組。元組中第一個元素是模式匹配字符串(正則表達式);第二個元素是那個模式將使用的視圖函數。

簡單來說,我們只是告訴 Django,所有指向 URL /hello/ 的請求都應由 hello 這個視圖函數來處理。

Python 搜索路徑

Python 搜索路徑 就是使用 import 語句時,Python 所查找的系統目錄清單。

舉例來說,假定你將 Python 路徑設置為

['','/usr/lib/python2.4/site-packages','/home/username/djcode/']

如果執行代碼from foo import bar ,Python 將會首先在當前目錄查找 foo.py 模塊( Python 路徑第一項的空字符串表示當前目錄)。 如果文件不存在,Python將查找 /usr/lib/python2.4/site-packages/foo.py 文件。

如果你想看Python搜索路徑的值,運行Python交互解釋器,然后輸入:

>>> import sys
>>> print sys.path

通常,你不必關心 Python 搜索路徑的設置。 Python 和 Django 會在后臺自動幫你處理好。

討論一下URLpattern的語法是值得的,因為它不是顯而易見的。 雖然我們想匹配地址/hello/,但是模式看上去與這有點差別。 這就是為什么:

Django在檢查URL模式前,移除每一個申請的URL開頭的斜杠(/)。 這意味著我們為/hello/寫URL模式不用包含斜杠(/)。(剛開始,這樣可能看起來不直觀,但這樣的要求簡化了許多工作,如URL模式內嵌,我們將在第八章談及。)

模式包含了一個尖號(^)和一個美元符號($)。這些都是正則表達式符號,并且有特定的含義: 上箭頭要求表達式對字符串的頭部進行匹配,美元符號則要求表達式對字符串的尾部進行匹配。

最好還是用范例來說明一下這個概念。 如果我們用尾部不是$的模式’^hello/’,那么任何以/hello/開頭的URL將會匹配,例如:/hello/foo 和/hello/bar,而不僅僅是/hello/。類似地,如果我們忽略了尖號(^),即’hello/$’,那么任何以hello/結尾的URL將會匹配,例如:/foo/bar/hello/。如果我們簡單使用hello/,即沒有^開頭和$結尾,那么任何包含hello/的URL將會匹配,如:/foo/hello/bar。因此,我們使用這兩個符號以確保只有/hello/匹配,不多也不少。

你大多數的URL模式會以^開始、以$結束,但是擁有復雜匹配的靈活性會更好。

你可能會問:如果有人申請訪問/hello(尾部沒有斜杠/)會怎樣。 因為我們的URL模式要求尾部有一個斜杠(/),那個申請URL將不匹配。 然而,默認地,任何不匹配或尾部沒有斜杠(/)的申請URL,將被重定向至尾部包含斜杠的相同字眼的URL。 (這是受配置文件setting中APPEND_SLASH項控制的,參見附件D。)
如果你是喜歡所有URL都以’/’結尾的人(Django開發者的偏愛),那么你只需要在每個URL后添加斜杠,并且設置”APPEND_SLASH”為”True”. 如果不喜歡URL以斜杠結尾或者根據每個URL來決定,那么需要設置”APPEND_SLASH”為”False”,并且根據你自己的意愿來添加結尾斜杠/在URL模式后.

另外需要注意的是,我們把hello視圖函數作為一個對象傳遞,而不是調用它。 這是 Python (及其它動態語言的) 的一個重要特性: 函數是一級對象(first-class objects), 也就是說你可以像傳遞其它變量一樣傳遞它們。 很酷吧?

啟動Django開發服務器來測試修改好的 URLconf, 運行命令行 python manage.py runserver 。 (如果你讓它一直運行也可以,開發服務器會自動監測代碼改動并自動重新載入,所以不需要手工重啟) 開發服務器的地址是http://127.0.0.1:8000/ ,打開你的瀏覽器訪問 http://127.0.0.1:8000/hello/ 。 你就可以看到輸出結果了。 開發服務器將自動檢測Python代碼的更改來做必要的重新加載, 所以你不需要重啟Server在代碼更改之后。服務器運行地址 http://127.0.0.1:8000/ ,所以打開瀏覽器直接輸入 http://127.0.0.1:8000/hello/ ,你將看到由你的Django視圖輸出的Hello world。

萬歲! 你已經創建了第一個Django的web頁面。

正則表達式

正則表達式 (或 regexes ) 是通用的文本模式匹配的方法。 Django URLconfs 允許你 使用任意的正則表達式來做強有力的URL映射,不過通常你實際上可能只需要使用很少的一 部分功能。 這里是一些基本的語法。

符號匹配
. (dot)任意單一字符
\d任意一位數字
[A-Z]A 到 Z中任意一個字符(大寫)
[a-z]a 到 z中任意一個字符(小寫)
[A-Za-z]a 到 z中任意一個字符(不區分大小寫)
+匹配一個或更多 (例如, \d+ 匹配一個或 多個數字字符)
[^/]+一個或多個不為‘/’的字符
*零個或一個之前的表達式(例如:\d? 匹配零個或一個數字)
*匹配0個或更多 (例如, \d* 匹配0個 或更多數字字符)
{1,3}介于一個和三個(包含)之前的表達式(例如,\d{1,3}匹配一個或兩個或三個數字)

有關正則表達式的更多內容,請訪問 http://www.djangoproject.com/r/python/re-module/.

關于“404錯誤”的快速參考

目前,我們的URLconf只定義了一個單獨的URL模式: 處理URL /hello/ 。 當請求其他URL會怎么樣呢?

讓我們試試看,運行Django開發服務器并訪問類似 http://127.0.0.1:8000/goodbye/ 或者http://127.0.0.1:8000/hello/subdirectory/ ,甚至 http://127.0.0.1:8000/ (網站根目錄)。 你將會看到一個 “Page not found” 頁面(圖 3-1)。 因為你的URL申請在URLconf中沒有定義,所以Django顯示這條信息。

2015-06-26/558d267f427f5

圖3-1: Django的404 Error頁

這個頁面比原始的404錯誤信息更加實用。 它同時精確的告訴你Django調用哪個URLconf及其包含的每個模式。 這樣,你應該能了解到為什么這個請求會拋出404錯誤。

當然,這些敏感的信息應該只呈現給你-開發者。 如果是部署到了因特網上的站點就不應該暴露 這些信息。 出于這個考慮,這個“Page not found”頁面只會在 調試模式(debug mode) 下 顯示。 我們將在以后說明怎么關閉調試模式。

關于網站根目錄的快速參考。

在最后一節,如果你想通過http://127.0.0.1:8000/看網站根目錄你將看到一個404錯誤消息。Django不會增加任何東西在網站根目錄,在任何情況下這個URL都不是特殊的 就像在URLconf中的其他條目一樣,它也依賴于指定給它的URL模式.

盡管匹配網站根目錄的URL模式不能想象,但是還是值得提一下的. 當為網站根目錄實現一個視圖,你需要使用URL模式‘^$’ , 它代表一個空字符串。 例如:

from mysite.views import hello, my_homepage_view

urlpatterns = patterns('',
    url(r'^$', my_homepage_view),
    # ...
)

Django是怎么處理請求的

在繼續我們的第二個視圖功能之前,讓我們暫停一下去了解更多一些有關Django是怎么工作的知識. 具體地說,當你通過在瀏覽器里敲http://127.0.0.1:8000/hello/來訪問Hello world消息得時候,Django在后臺有些什么動作呢?

所有均開始于setting文件。當你運行python manage.py runserver,腳本將在于manage.py同一個目錄下查找名為setting.py的文件。這個文件包含了所有有關這個Django項目的配置信息,均大寫: TEMPLATE_DIRS , DATABASE_NAME , 等. 最重要的設置時ROOT_URLCONF,它將作為URLconf告訴Django在這個站點中那些Python的模塊將被用到

還記得什么時候django-admin.py startproject創建文件settings.py和urls.py嗎?自動創建的settings.py包含一個ROOT_URLCONF配置用來指向自動產生的urls.py. 打開文件settings.py你將看到如下:

ROOT_URLCONF = 'mysite.urls'

相對應的文件是mysite/urls.py

當訪問 URL /hello/ 時,Django 根據 ROOT_URLCONF 的設置裝載 URLconf 。 然后按順序逐個匹配URLconf里的URLpatterns,直到找到一個匹配的。 當找到這個匹配 的URLpatterns就調用相關聯的view函數,并把HttpRequest 對象作為第一個參數。 (稍后再給出 HttpRequest 的更多信息) (我們將在后面看到HttpRequest的標準)

正如我們在第一個視圖例子里面看到的,一個視圖功能必須返回一個HttpResponse。 一旦做完,Django將完成剩余的轉換Python的對象到一個合適的帶有HTTP頭和body的Web Response,(例如,網頁內容)。

總結一下:

  1. 進來的請求轉入/hello/.
  2. Django通過在ROOT_URLCONF配置來決定根URLconf.
  3. Django在URLconf中的所有URL模式中,查找第一個匹配/hello/的條目。
  4. 如果找到匹配,將調用相應的視圖函數
  5. 視圖函數返回一個HttpResponse
  6. Django轉換HttpResponse為一個適合的HTTP response, 以Web page顯示出來

你現在知道了怎么做一個 Django-powered 頁面了,真的很簡單,只需要寫視圖函數并用 URLconfs把它們和URLs對應起來。 你可能會認為用一系列正則表達式將URLs映射到函數也許會比較慢,但事實卻會讓你驚訝。

第二個視圖: 動態內容

我們的Hello world視圖是用來演示基本的Django是如何工作的,但是它不是一個動態網頁的例子,因為網頁的內容一直是一樣的. 每次去查看/hello/,你將會看到相同的內容,它類似一個靜態HTML文件。

我們的第二個視圖,將更多的放些動態的東西例如當前日期和時間顯示在網頁上 這將非常好,簡單的下一步,因為它不引入了數據庫或者任何用戶的輸入,僅僅是輸出顯示你的服務器的內部時鐘. 它僅僅有限度的比Helloworld刺激一些,但是它將演示一些新的概念

這個視圖需要做兩件事情: 計算當前日期和時間,并返回包含這些值的HttpResponse 如果你對python很有經驗,那肯定知道在python中需要利用datetime模塊去計算時間 下面演示如何去使用它:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2008, 12, 13, 14, 9, 39, 2731)
>>> print now
2008-12-13 14:09:39.002731

以上代碼很簡單,并沒有涉及Django。 它僅僅是Python代碼。 需要強調的是,你應該意識到哪些是純Python代碼,哪些是Django特性代碼。 (見上) 因為你學習了Django,希望你能將Django的知識應用在那些不一定需要使用Django的項目上。

為了讓Django視圖顯示當前日期和時間,我們僅需要把語句:datetime.datetime.now()放入視圖函數,然后返回一個HttpResponse對象即可。代碼如下:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

正如我們的hello函數一樣,這個函數也保存在view.py中。為了簡潔,上面我們隱藏了hello函數。下面是完整的view.py文件內容:

from django.http import HttpResponse
import datetime

def hello(request):
    return HttpResponse("Hello world")

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

(從現在開始,如非必要,本文不再重復列出先前的代碼。 你應該懂得識別哪些是新代碼,哪些是先前的。) (見上)

讓我們分析一下改動后的views.py:

在文件頂端,我們添加了一條語句:import datetime。這樣就可以計算日期了。
函數中的第一行代碼計算當前日期和時間,并以 datetime.datetime 對象的形式保存為局部變量 now 。
函數的第二行代碼用 Python 的格式化字符串(format-string)功能構造了一段 HTML 響應。 字符串中的%s是占位符,字符串后面的百分號表示用它后面的變量now的值來代替%s。變量%s是一個datetime.datetime對象。它雖然不是一個字符串,但是%s(格式化字符串)會把它轉換成字符串,如:2008-12-13 14:09:39.002731。這將導致HTML的輸出字符串為:It is now 2008-12-13 14:09:39.002731。

(目前HTML是有錯誤的,但我們這樣做是為了保持例子的簡短。)

最后,正如我們剛才寫的hello函數一樣,視圖返回一個HttpResponse對象,它包含生成的響應。

添加上述代碼之后,還要在urls.py中添加URL模式,以告訴Django由哪一個URL來處理這個視圖。 用/time/之類的字眼易于理解:

from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime

urlpatterns = patterns('',
    ('^hello/$', hello),
    ('^time/$', current_datetime),
)

這里,我們修改了兩個地方。 首先,在頂部導入current_datetime函數; 其次,也是比較重要的:添加URL模式來映射URL中的/time/和新視圖。 理解了么?

寫好視圖并且更新URLconf之后,運行命令python manage.py runserver以啟動服務,在瀏覽器中輸入http://127.0.0.1:8000/time/。 你將看到當前的日期和時間。

Django時區

視乎你的機器,顯示的日期與時間可能和實際的相差幾個小時。 這是因為Django是有時區意識的,并且默認時區為America/Chicago。 (它必須有個值,它的默認值是Django的誕生地:美國/芝加哥)如果你處在別的時區,你需要在settings.py文件中更改這個值。請參見它里面的注釋,以獲得最新世界時區列表。

URL配置和松耦合

現在是好時機來指出Django和URL配置背后的哲學: 松耦合 原則。 簡單的說,松耦合是一個 重要的保證互換性的軟件開發方法。

Django的URL配置就是一個很好的例子。 在Django的應用程序中,URL的定義和視圖函數之間是松 耦合的,換句話說,決定URL返回哪個視圖函數和實現這個視圖函數是在兩個不同的地方。 這使得 開發人員可以修改一塊而不會影響另一塊。

例如,考慮一下current_datetime視圖。 如果我們想把它的URL 從原來的 /time/ 改變到 /currenttime/ ,我們只需要快速的修改一下URL配置即可, 不用擔心這個函數的內部實現。 同樣的,如果我們想要修改這個函數的內部實現也不用擔心會影響 到對應的URL。

此外,如果我們想要輸出這個函數到 一些 URL, 我們只需要修改URL配置而不用 去改動視圖的代碼。 在這個例子里,current_datetime被兩個URL使用。 這是一個故弄玄虛的例子,但這個方法遲早會用得上。

urlpatterns = patterns('',
    ('^hello/$', hello),
    ('^time/$', current_datetime),
    ('^another-time-page/$', current_datetime),
)

URLconf和視圖是松耦合的。 我們將在本書中繼續給出這一重要哲學的相關例子。

第三個視圖 動態URL

在我們的current_datetime 視圖范例中,盡管內容是動態的,但是URL ( /time/ )是靜態的。 在 大多數動態web應用程序,URL通常都包含有相關的參數。 舉個例子,一家在線書店會為每一本書提供一個URL,如:/books/243/、/books/81196/。

讓我們創建第三個視圖來顯示當前時間和加上時間偏差量的時間,設計是這樣的: /time/plus/1/ 顯示當前時間+1個小時的頁面 /time/plus/2/ 顯示當前時間+2個小時的頁面 /time/plus/3/ 顯示當前時間+3個小時的頁面,以此類推。

新手可能會考慮寫不同的視圖函數來處理每個時間偏差量,URL配置看起來就象這樣:

urlpatterns = patterns('',
    ('^time/$', current_datetime),
    ('^time/plus/1/$', one_hour_ahead),
    ('^time/plus/2/$', two_hours_ahead),
    ('^time/plus/3/$', three_hours_ahead),
    ('^time/plus/4/$', four_hours_ahead),
)

很明顯,這樣處理是不太妥當的。 不但有很多冗余的視圖函數,而且整個應用也被限制了只支持 預先定義好的時間段,2小時,3小時,或者4小時。 如果哪天我們要實現 5 小時,我們就 不得不再單獨創建新的視圖函數和配置URL,既重復又混亂。 我們需要在這里做一點抽象,提取 一些共同的東西出來。

關于漂亮URL的一點建議

如果你有其它web平臺的開發經驗(如PHP或Java),你可能會想:嘿!讓我們用查詢字符串參數吧! 就像/time/plus?hours=3里面的小時應該在查詢字符串中被參數hours指定(問號后面的是參數)。

你 可以 在Django里也這樣做 (如果你真的想要這樣做,我們稍后會告訴你怎么做), 但是Django的一個核心理念就是URL必須看起來漂亮。 URL /time/plus/3/ 更加清晰, 更簡單,也更有可讀性,可以很容易的大聲念出來,因為它是純文本,沒有查詢字符串那么 復雜。 漂亮的URL就像是高質量的Web應用的一個標志。

Django的URL配置系統可以使你很容易的設置漂亮的URL,而盡量不要考慮它的 反面 。

那么,我們如何設計程序來處理任意數量的時差? 答案是:使用通配符(wildcard URLpatterns)。正如我們之前提到過,一個URL模式就是一個正則表達式。因此,這里可以使用d+來匹配1個以上的數字。

urlpatterns = patterns('',
    # ...
    (r'^time/plus/\d+/$', hours_ahead),
    # ...
)

這里使用# …來表示省略了其它可能存在的URL模式定義。 (見上)

這個URL模式將匹配類似 /time/plus/2/ , /time/plus/25/ ,甚至 /time/plus/100000000000/ 的任何URL。 更進一步,讓我們把它限制在最大允許99個小時, 這樣我們就只允許一個或兩個數字,正則表達式的語法就是\d{1,2} :

(r'^time/plus/\d{1,2}/$', hours_ahead),

備注

在建造Web應用的時候,盡可能多考慮可能的數據輸入是很重要的,然后決定哪些我們可以接受。 在這里我們就設置了99個小時的時間段限制。

另外一個重點,正則表達式字符串的開頭字母“r”。 它告訴Python這是個原始字符串,不需要處理里面的反斜杠(轉義字符)。 在普通Python字符串中,反斜杠用于特殊字符的轉義。比如n轉義成一個換行符。 當你用r把它標示為一個原始字符串后,Python不再視其中的反斜杠為轉義字符。也就是說,“n”是兩個字符串:“”和“n”。由于反斜杠在Python代碼和正則表達式中有沖突,因此建議你在Python定義正則表達式時都使用原始字符串。 從現在開始,本文所有URL模式都用原始字符串。

現在我們已經設計了一個帶通配符的URL,我們需要一個方法把它傳遞到視圖函數里去,這樣 我們只用一個視圖函數就可以處理所有的時間段了。 我們使用圓括號把參數在URL模式里標識 出來。 在這個例子中,我們想要把這些數字作為參數,用圓括號把 \d{1,2} 包圍起來:

(r'^time/plus/(\d{1,2})/$', hours_ahead),

如果你熟悉正則表達式,那么你應該已經了解,正則表達式也是用圓括號來從文本里 提取 數據的。

最終的URLconf包含上面兩個視圖,如:

from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime, hours_ahead

urlpatterns = patterns('',
    (r'^hello/$', hello),
    (r'^time/$', current_datetime),
    (r'^time/plus/(\d{1,2})/$', hours_ahead),
)

現在開始寫 hours_ahead 視圖。

編碼次序

這個例子中,我們先寫了URLpattern ,然后是視圖,但是在前面的例子中, 我們先寫了視圖,然后是URLpattern 。 哪一種方式比較好?

嗯,怎么說呢,每個開發者是不一樣的。

如果你是喜歡從總體上來把握事物(注: 或譯為“大局觀”)類型的人,你應該會想在項目開始 的時候就寫下所有的URL配置。

如果你從更像是一個自底向上的開發者,你可能更喜歡先寫視圖, 然后把它們掛接到URL上。 這同樣是可以的。

最后,取決與你喜歡哪種技術,兩種方法都是可以的。 (見上)

hours_ahead 和我們以前寫的 current_datetime 很象,關鍵的區別在于: 它多了一個額外參數,時間差。 以下是view代碼:

from django.http import Http404, HttpResponse
import datetime

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)

讓我們逐行分析一下代碼:

視圖函數, hours_ahead , 有 兩個 參數: request 和 offset . (見上)

request 是一個 HttpRequest 對象, 就像在 current_datetime 中一樣. 再說一次好了: 每一個視圖 _總是_以一個 HttpRequest 對象作為 它的第一個參數。 (見上)

offset 是從匹配的URL里提取出來的。 例如:如果請求URL是/time/plus/3/,那么offset將會是3;如果請求URL是/time/plus/21/,那么offset將會是21。請注意:捕獲值永遠都是字符串(string)類型,而不會是整數(integer)類型,即使這個字符串全由數字構成(如:“21”)。

(從技術上來說,捕獲值總是Unicode objects,而不是簡單的Python字節串,但目前不需要擔心這些差別。)

在這里我們命名變量為 offset ,你也可以任意命名它,只要符合Python 的語法。 變量名是無關緊要的,重要的是它的位置,它是這個函數的第二個 參數 (在 request 的后面)。 你還可以使用關鍵字來定義它,而不是用 位置。

我們在這個函數中要做的第一件事情就是在 offset 上調用 int() . 這會把這個字符串值轉換為整數。

請留意:如果你在一個不能轉換成整數類型的值上調用int(),Python將拋出一個ValueError異常。如:int(‘foo’)。在這個例子中,如果我們遇到ValueError異常,我們將轉為拋出django.http.Http404異常——正如你想象的那樣:最終顯示404頁面(提示信息:頁面不存在)。

機靈的讀者可能會問: 我們在URL模式中用正則表達式(d{1,2})約束它,僅接受數字怎么樣?這樣無論如何,offset都是由數字構成的。 答案是:我們不會這么做,因為URLpattern提供的是“適度但有用”級別的輸入校驗。萬一這個視圖函數被其它方式調用,我們仍需自行檢查ValueError。 實踐證明,在實現視圖函數時,不臆測參數值的做法是比較好的。 松散耦合,還記得么?

下一行,計算當前日期/時間,然后加上適當的小時數。 在current_datetime視圖中,我們已經見過datetime.datetime.now()。這里新的概念是執行日期/時間的算術操作。我們需要創建一個datetime.timedelta對象和增加一個datetime.datetime對象。 結果保存在變量dt中。

這一行還說明了,我們為什么在offset上調用int()——datetime.timedelta函數要求hours參數必須為整數類型。

這行和前面的那行的的一個微小差別就是,它使用帶有兩個值的Python的格式化字符串功能, 而不僅僅是一個值。 因此,在字符串中有兩個 %s 符號和一個以進行插入的值的元組: (offset, dt) 。
最終,返回一個HTML的HttpResponse。 如今,這種方式已經過時了。

在完成視圖函數和URL配置編寫后,啟動Django開發服務器,用瀏覽器訪問http://127.0.0.1:8000/time/plus/3/ 來確認它工作正常。 然后是 http://127.0.0.1:8000/time/plus/5/ 。再然后是 http://127.0.0.1:8000/time/plus/24/ 。最后,訪問 http://127.0.0.1:8000/time/plus/100/ 來檢驗URL配置里設置的模式是否只 接受一個或兩個數字;Django會顯示一個 Page not found error 頁面, 和以前看到的 404 錯誤一樣。 訪問URL http://127.0.0.1:8000/time/plus/ (沒有 定義時間差) 也會拋出404錯誤。

Django 漂亮的出錯頁面

花幾分鐘時間欣賞一下我們寫好的Web應用程序,然后我們再來搞點小破壞。 我們故意在 views.py 文件中引入一項 Python 錯誤,注釋掉 hours_ahead 視圖中的 offset = int(offset) 一行。

def hours_ahead(request, offset):
    # try:
    #     offset = int(offset)
    # except ValueError:
    #     raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)

啟動開發服務器,然后訪問 /time/plus/3/ 。你會看到一個包含大量信息的出錯頁,最上面 的一條 TypeError信息是: "unsupported type for timedelta hours component:  unicode" .

怎么回事呢? 是的, datetime.timedelta 函數要求 hours 參數必須為整型, 而我們注釋掉了將 offset 轉為整型的代碼。 這樣導致 datetime.timedelta 彈出 TypeError 異常。

這個例子是為了展示 Django 的出錯頁面。 我們來花些時間看一看這個出錯頁,了解一下其中 給出了哪些信息。

以下是值得注意的一些要點:

在頁面頂部,你可以得到關鍵的異常信息: 異常數據類型、異常的參數 (如本例中的 "unsupported type")、在哪個文件中引發了異常、出錯的行號等等。
在關鍵異常信息下方,該頁面顯示了對該異常的完整 Python 追蹤信息。 這類似于你在 Python 命令行解釋器中獲得的追溯信息,只不過后者更具交互性。 對棧中的每一幀,Django 均顯示了其文件名、函數或方法名、行號及該行源代碼。
點擊該行代碼 (以深灰色顯示),你可以看到出錯行的前后幾行,從而得知相關上下文情況。

點擊棧中的任何一幀的“Local vars”可以看到一個所有局部變量的列表,以及在出錯 那一幀時它們的值。 這些調試信息相當有用。
注意“Traceback”下面的“Switch to copy-and-paste view”文字。 點擊這些字,追溯會 切換另一個視圖,它讓你很容易地復制和粘貼這些內容。 當你想同其他人分享這些異常 追溯以獲得技術支持時(比如在 Django 的 IRC 聊天室或郵件列表中),可以使用它。
你按一下下面的“Share this traceback on a public Web site”按鈕,它將會完成這項工作。 點擊它以傳回追溯信息至http://www.dpaste.com/,在那里你可以得到一個單獨的URL并與其他人分享你的追溯信息。
接下來的“Request information”部分包含了有關產生錯誤的 Web 請求的大量信息: GET 和 POST、cookie 值、元數據(象 CGI 頭)。 在附錄H里給出了request的對象的 完整參考。
Request信息的下面,“Settings”列出了 Django 使用的具體配置信息。 (我們已經提及過ROOT_URLCONF,接下來我們將向你展示各式的Django設置。 附錄D覆蓋了所有可用的設置。)

Django 的出錯頁某些情況下有能力顯示更多的信息,比如模板語法錯誤。 我們討論 Django 模板系統時再說它們。 現在,取消 offset = int(offset) 這行的注釋,讓它重新正常 工作。

不知道你是不是那種使用小心放置的 print 語句來幫助調試的程序員? 你其實可以用 Django 出錯頁來做這些,而不用 print 語句。 在你視圖的任何位置,臨時插入一個 assert False 來觸發出錯頁。 然后,你就可以看到局部變量和程序語句了。 這里有個使用hours_ahead視圖的例子:

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    assert False
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)

最后,很顯然這些信息很多是敏感的,它暴露了你 Python 代碼的內部結構以及 Django 配置,在 Internet 上公開這信息是很愚蠢的。 不懷好意的人會嘗試使用它攻擊你的 Web 應用程序,做些下流之事。 因此,Django 出錯信息僅在 debug 模式下才會顯現。 我們稍后 說明如何禁用 debug 模式。 現在,你只要知道 Django 服務器在你開啟它時默認運行在 debug 模式就行了。 (聽起來很熟悉? 頁面沒有發現錯誤,如前所述,工作正常。)

下一章

目前為止,我們已經寫好了視圖函數和硬編碼的HTML。 在演示核心概念時,我們所作的是為了保持簡單。但是在現實世界中,這差不多總是個壞主意。

幸運的是,Django內建有一個簡單有強大的模板處理引擎來讓你分離兩種工作: 下一章,我們將學習模板引擎。

關閉
程序員人生
主站蜘蛛池模板: 日本在线中文 | 亚洲精品在线观看视频 | 成人免费网站 | 亚洲成人av观看 | 国产一区二区三区在线看 | 国产成人99久久亚洲综合精品 | 国产一级久久 | 日韩视频免费 | 国产精品成人影院 | 999久久久精品视频 国产第91页 | 国产美女高潮 | 亚洲精品久久久久久久久久久 | 日韩中文字幕网站 | 日韩国产综合av | 欧美一区在线视频 | 中文字幕在线观看一区二区 | 中文字幕在线三区 | 黄色短视频在线播放 | 国产亚洲精品久 | 国产一区二区视频在线观看免费 | 亚洲国产精品网站 | 玖玖色资源 | 夜夜骑夜夜骑 | 亚洲视频二区 | www.成人.com| 亚洲国产精品女人久久久 | 色婷婷5月 | 欧美,日韩,国产在线 | 日韩一级视频 | 日韩精品中文字幕一区二区三区 | 免费黄色一级大片 | 国产一区二区在线免费观看 | 天天插天天射天天操 | 91区国产 | 亚洲一区二区三区四区五区中文 | 一区二区日韩精品 | 国产成人福利在线 | 99精品视频在线观看 | 一本色道久久88综合亚洲精品ⅰ | 天天色图| 久久久久国产美女免费网站 |