多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

中國(guó)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2

django教程

Django 視圖和URL配置

閱讀 (2360)

前一章中,我們解釋了如何建立一個(gè) Django 項(xiàng)目并啟動(dòng) Django 開發(fā)服務(wù)器。 在這一章,你將會(huì)學(xué)到用Django創(chuàng)建動(dòng)態(tài)網(wǎng)頁(yè)的基本知識(shí)。

你的第一個(gè)基于Django的頁(yè)面: Hello World

正如我們的第一個(gè)目標(biāo),創(chuàng)建一個(gè)網(wǎng)頁(yè),用來輸出這個(gè)著名的示例信息:

Hello world.

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

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

第一份視圖:

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

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

from django.http import HttpResponse

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

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

首先,我們從 django.http 模塊導(dǎo)入(import) HttpResponse 類。參閱附錄 H 了解更多關(guān)于 HttpRequest和 HttpResponse 的細(xì)節(jié)。 我們需要導(dǎo)入這些類,因?yàn)槲覀儠?huì)在后面用到。

接下來,我們定義一個(gè)叫做hello 的視圖函數(shù)。

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

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

這個(gè)函數(shù)只有簡(jiǎn)單的一行代碼: 它僅僅返回一個(gè)HttpResponse對(duì)象,這個(gè)對(duì)象包含了文本“Hello world”。

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

你的第一個(gè)URLconf

現(xiàn)在,如果你再運(yùn)行:python manage.py runserver,你還將看到Django的歡迎頁(yè)面,而看不到我們剛才寫的Hello world顯示頁(yè)面。 那是因?yàn)槲覀兊膍ysite項(xiàng)目還對(duì)hello視圖一無所知。我們需要通過一個(gè)詳細(xì)描述的URL來顯式的告訴它并且激活這個(gè)視圖。 (繼續(xù)我們剛才類似發(fā)布靜態(tài)HTML文件的例子?,F(xiàn)在我們已經(jīng)創(chuàng)建了HTML文件,但還沒有把它上傳至服務(wù)器的目錄。)為了綁定視圖函數(shù)和URL,我們使用URLconf。

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

前一章中執(zhí)行 django-admin.py startproject 時(shí),該腳本會(huì)自動(dòng)為你建了一份 URLconf(即 urls.py 文件)。 默認(rèn)的urls.py會(huì)像下面這個(gè)樣子:

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)),
)

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

from django.conf.urls.defaults import *

urlpatterns = patterns('',
)

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

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

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

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

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

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

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

我們做了兩處修改。

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

簡(jiǎn)單來說,我們只是告訴 Django,所有指向 URL /hello/ 的請(qǐng)求都應(yīng)由 hello 這個(gè)視圖函數(shù)來處理。

Python 搜索路徑

Python 搜索路徑 就是使用 import 語(yǔ)句時(shí),Python 所查找的系統(tǒng)目錄清單。

舉例來說,假定你將 Python 路徑設(shè)置為

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

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

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

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

通常,你不必關(guān)心 Python 搜索路徑的設(shè)置。 Python 和 Django 會(huì)在后臺(tái)自動(dòng)幫你處理好。

討論一下URLpattern的語(yǔ)法是值得的,因?yàn)樗皇秋@而易見的。 雖然我們想匹配地址/hello/,但是模式看上去與這有點(diǎn)差別。 這就是為什么:

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

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

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

你大多數(shù)的URL模式會(huì)以^開始、以$結(jié)束,但是擁有復(fù)雜匹配的靈活性會(huì)更好。

你可能會(huì)問:如果有人申請(qǐng)?jiān)L問/hello(尾部沒有斜杠/)會(huì)怎樣。 因?yàn)槲覀兊腢RL模式要求尾部有一個(gè)斜杠(/),那個(gè)申請(qǐng)URL將不匹配。 然而,默認(rèn)地,任何不匹配或尾部沒有斜杠(/)的申請(qǐng)URL,將被重定向至尾部包含斜杠的相同字眼的URL。 (這是受配置文件setting中APPEND_SLASH項(xiàng)控制的,參見附件D。)
如果你是喜歡所有URL都以’/’結(jié)尾的人(Django開發(fā)者的偏愛),那么你只需要在每個(gè)URL后添加斜杠,并且設(shè)置”APPEND_SLASH”為”True”. 如果不喜歡URL以斜杠結(jié)尾或者根據(jù)每個(gè)URL來決定,那么需要設(shè)置”APPEND_SLASH”為”False”,并且根據(jù)你自己的意愿來添加結(jié)尾斜杠/在URL模式后.

另外需要注意的是,我們把hello視圖函數(shù)作為一個(gè)對(duì)象傳遞,而不是調(diào)用它。 這是 Python (及其它動(dòng)態(tài)語(yǔ)言的) 的一個(gè)重要特性: 函數(shù)是一級(jí)對(duì)象(first-class objects), 也就是說你可以像傳遞其它變量一樣傳遞它們。 很酷吧?

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

萬歲! 你已經(jīng)創(chuàng)建了第一個(gè)Django的web頁(yè)面。

正則表達(dá)式

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

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

有關(guān)正則表達(dá)式的更多內(nèi)容,請(qǐng)?jiān)L問 http://www.djangoproject.com/r/python/re-module/.

關(guān)于“404錯(cuò)誤”的快速參考

目前,我們的URLconf只定義了一個(gè)單獨(dú)的URL模式: 處理URL /hello/ 。 當(dāng)請(qǐng)求其他URL會(huì)怎么樣呢?

讓我們?cè)囋嚳?,運(yùn)行Django開發(fā)服務(wù)器并訪問類似 http://127.0.0.1:8000/goodbye/ 或者h(yuǎn)ttp://127.0.0.1:8000/hello/subdirectory/ ,甚至 http://127.0.0.1:8000/ (網(wǎng)站根目錄)。 你將會(huì)看到一個(gè) “Page not found” 頁(yè)面(圖 3-1)。 因?yàn)槟愕腢RL申請(qǐng)?jiān)赨RLconf中沒有定義,所以Django顯示這條信息。

2015-06-26/558d267f427f5

圖3-1: Django的404 Error頁(yè)

這個(gè)頁(yè)面比原始的404錯(cuò)誤信息更加實(shí)用。 它同時(shí)精確的告訴你Django調(diào)用哪個(gè)URLconf及其包含的每個(gè)模式。 這樣,你應(yīng)該能了解到為什么這個(gè)請(qǐng)求會(huì)拋出404錯(cuò)誤。

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

關(guān)于網(wǎng)站根目錄的快速參考。

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

盡管匹配網(wǎng)站根目錄的URL模式不能想象,但是還是值得提一下的. 當(dāng)為網(wǎng)站根目錄實(shí)現(xiàn)一個(gè)視圖,你需要使用URL模式‘^$’ , 它代表一個(gè)空字符串。 例如:

from mysite.views import hello, my_homepage_view

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

Django是怎么處理請(qǐng)求的

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

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

還記得什么時(shí)候django-admin.py startproject創(chuàng)建文件settings.py和urls.py嗎?自動(dòng)創(chuàng)建的settings.py包含一個(gè)ROOT_URLCONF配置用來指向自動(dòng)產(chǎn)生的urls.py. 打開文件settings.py你將看到如下:

ROOT_URLCONF = 'mysite.urls'

相對(duì)應(yīng)的文件是mysite/urls.py

當(dāng)訪問 URL /hello/ 時(shí),Django 根據(jù) ROOT_URLCONF 的設(shè)置裝載 URLconf 。 然后按順序逐個(gè)匹配URLconf里的URLpatterns,直到找到一個(gè)匹配的。 當(dāng)找到這個(gè)匹配 的URLpatterns就調(diào)用相關(guān)聯(lián)的view函數(shù),并把HttpRequest 對(duì)象作為第一個(gè)參數(shù)。 (稍后再給出 HttpRequest 的更多信息) (我們將在后面看到HttpRequest的標(biāo)準(zhǔn))

正如我們?cè)诘谝粋€(gè)視圖例子里面看到的,一個(gè)視圖功能必須返回一個(gè)HttpResponse。 一旦做完,Django將完成剩余的轉(zhuǎn)換Python的對(duì)象到一個(gè)合適的帶有HTTP頭和body的Web Response,(例如,網(wǎng)頁(yè)內(nèi)容)。

總結(jié)一下:

  1. 進(jìn)來的請(qǐng)求轉(zhuǎn)入/hello/.
  2. Django通過在ROOT_URLCONF配置來決定根URLconf.
  3. Django在URLconf中的所有URL模式中,查找第一個(gè)匹配/hello/的條目。
  4. 如果找到匹配,將調(diào)用相應(yīng)的視圖函數(shù)
  5. 視圖函數(shù)返回一個(gè)HttpResponse
  6. Django轉(zhuǎn)換HttpResponse為一個(gè)適合的HTTP response, 以Web page顯示出來

你現(xiàn)在知道了怎么做一個(gè) Django-powered 頁(yè)面了,真的很簡(jiǎn)單,只需要寫視圖函數(shù)并用 URLconfs把它們和URLs對(duì)應(yīng)起來。 你可能會(huì)認(rèn)為用一系列正則表達(dá)式將URLs映射到函數(shù)也許會(huì)比較慢,但事實(shí)卻會(huì)讓你驚訝。

第二個(gè)視圖: 動(dòng)態(tài)內(nèi)容

我們的Hello world視圖是用來演示基本的Django是如何工作的,但是它不是一個(gè)動(dòng)態(tài)網(wǎng)頁(yè)的例子,因?yàn)榫W(wǎng)頁(yè)的內(nèi)容一直是一樣的. 每次去查看/hello/,你將會(huì)看到相同的內(nèi)容,它類似一個(gè)靜態(tài)HTML文件。

我們的第二個(gè)視圖,將更多的放些動(dòng)態(tài)的東西例如當(dāng)前日期和時(shí)間顯示在網(wǎng)頁(yè)上 這將非常好,簡(jiǎn)單的下一步,因?yàn)樗灰肓藬?shù)據(jù)庫(kù)或者任何用戶的輸入,僅僅是輸出顯示你的服務(wù)器的內(nèi)部時(shí)鐘. 它僅僅有限度的比Helloworld刺激一些,但是它將演示一些新的概念

這個(gè)視圖需要做兩件事情: 計(jì)算當(dāng)前日期和時(shí)間,并返回包含這些值的HttpResponse 如果你對(duì)python很有經(jīng)驗(yàn),那肯定知道在python中需要利用datetime模塊去計(jì)算時(shí)間 下面演示如何去使用它:

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

以上代碼很簡(jiǎn)單,并沒有涉及Django。 它僅僅是Python代碼。 需要強(qiáng)調(diào)的是,你應(yīng)該意識(shí)到哪些是純Python代碼,哪些是Django特性代碼。 (見上) 因?yàn)槟銓W(xué)習(xí)了Django,希望你能將Django的知識(shí)應(yīng)用在那些不一定需要使用Django的項(xiàng)目上。

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

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函數(shù)一樣,這個(gè)函數(shù)也保存在view.py中。為了簡(jiǎn)潔,上面我們隱藏了hello函數(shù)。下面是完整的view.py文件內(nèi)容:

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)

(從現(xiàn)在開始,如非必要,本文不再重復(fù)列出先前的代碼。 你應(yīng)該懂得識(shí)別哪些是新代碼,哪些是先前的。) (見上)

讓我們分析一下改動(dòng)后的views.py:

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

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

最后,正如我們剛才寫的hello函數(shù)一樣,視圖返回一個(gè)HttpResponse對(duì)象,它包含生成的響應(yīng)。

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

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

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

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

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

Django時(shí)區(qū)

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

URL配置和松耦合

現(xiàn)在是好時(shí)機(jī)來指出Django和URL配置背后的哲學(xué): 松耦合 原則。 簡(jiǎn)單的說,松耦合是一個(gè) 重要的保證互換性的軟件開發(fā)方法。

Django的URL配置就是一個(gè)很好的例子。 在Django的應(yīng)用程序中,URL的定義和視圖函數(shù)之間是松 耦合的,換句話說,決定URL返回哪個(gè)視圖函數(shù)和實(shí)現(xiàn)這個(gè)視圖函數(shù)是在兩個(gè)不同的地方。 這使得 開發(fā)人員可以修改一塊而不會(huì)影響另一塊。

例如,考慮一下current_datetime視圖。 如果我們想把它的URL 從原來的 /time/ 改變到 /currenttime/ ,我們只需要快速的修改一下URL配置即可, 不用擔(dān)心這個(gè)函數(shù)的內(nèi)部實(shí)現(xiàn)。 同樣的,如果我們想要修改這個(gè)函數(shù)的內(nèi)部實(shí)現(xiàn)也不用擔(dān)心會(huì)影響 到對(duì)應(yīng)的URL。

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

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

URLconf和視圖是松耦合的。 我們將在本書中繼續(xù)給出這一重要哲學(xué)的相關(guān)例子。

第三個(gè)視圖 動(dòng)態(tài)URL

在我們的current_datetime 視圖范例中,盡管內(nèi)容是動(dòng)態(tài)的,但是URL ( /time/ )是靜態(tài)的。 在 大多數(shù)動(dòng)態(tài)web應(yīng)用程序,URL通常都包含有相關(guān)的參數(shù)。 舉個(gè)例子,一家在線書店會(huì)為每一本書提供一個(gè)URL,如:/books/243/、/books/81196/。

讓我們創(chuàng)建第三個(gè)視圖來顯示當(dāng)前時(shí)間和加上時(shí)間偏差量的時(shí)間,設(shè)計(jì)是這樣的: /time/plus/1/ 顯示當(dāng)前時(shí)間+1個(gè)小時(shí)的頁(yè)面 /time/plus/2/ 顯示當(dāng)前時(shí)間+2個(gè)小時(shí)的頁(yè)面 /time/plus/3/ 顯示當(dāng)前時(shí)間+3個(gè)小時(shí)的頁(yè)面,以此類推。

新手可能會(huì)考慮寫不同的視圖函數(shù)來處理每個(gè)時(shí)間偏差量,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),
)

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

關(guān)于漂亮URL的一點(diǎn)建議

如果你有其它web平臺(tái)的開發(fā)經(jīng)驗(yàn)(如PHP或Java),你可能會(huì)想:嘿!讓我們用查詢字符串參數(shù)吧! 就像/time/plus?hours=3里面的小時(shí)應(yīng)該在查詢字符串中被參數(shù)hours指定(問號(hào)后面的是參數(shù))。

你 可以 在Django里也這樣做 (如果你真的想要這樣做,我們稍后會(huì)告訴你怎么做), 但是Django的一個(gè)核心理念就是URL必須看起來漂亮。 URL /time/plus/3/ 更加清晰, 更簡(jiǎn)單,也更有可讀性,可以很容易的大聲念出來,因?yàn)樗羌兾谋?,沒有查詢字符串那么 復(fù)雜。 漂亮的URL就像是高質(zhì)量的Web應(yīng)用的一個(gè)標(biāo)志。

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

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

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

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

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

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

備注

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

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

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

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

如果你熟悉正則表達(dá)式,那么你應(yīng)該已經(jīng)了解,正則表達(dá)式也是用圓括號(hào)來從文本里 提取 數(shù)據(jù)的。

最終的URLconf包含上面兩個(gè)視圖,如:

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),
)

現(xiàn)在開始寫 hours_ahead 視圖。

編碼次序

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

嗯,怎么說呢,每個(gè)開發(fā)者是不一樣的。

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

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

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

hours_ahead 和我們以前寫的 current_datetime 很象,關(guān)鍵的區(qū)別在于: 它多了一個(gè)額外參數(shù),時(shí)間差。 以下是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)

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

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

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

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

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

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

我們?cè)谶@個(gè)函數(shù)中要做的第一件事情就是在 offset 上調(diào)用 int() . 這會(huì)把這個(gè)字符串值轉(zhuǎn)換為整數(shù)。

請(qǐng)留意:如果你在一個(gè)不能轉(zhuǎn)換成整數(shù)類型的值上調(diào)用int(),Python將拋出一個(gè)ValueError異常。如:int(‘foo’)。在這個(gè)例子中,如果我們遇到ValueError異常,我們將轉(zhuǎn)為拋出django.http.Http404異?!缒阆胂蟮哪菢樱鹤罱K顯示404頁(yè)面(提示信息:頁(yè)面不存在)。

機(jī)靈的讀者可能會(huì)問: 我們?cè)赨RL模式中用正則表達(dá)式(d{1,2})約束它,僅接受數(shù)字怎么樣?這樣無論如何,offset都是由數(shù)字構(gòu)成的。 答案是:我們不會(huì)這么做,因?yàn)閁RLpattern提供的是“適度但有用”級(jí)別的輸入校驗(yàn)。萬一這個(gè)視圖函數(shù)被其它方式調(diào)用,我們?nèi)孕枳孕袡z查ValueError。 實(shí)踐證明,在實(shí)現(xiàn)視圖函數(shù)時(shí),不臆測(cè)參數(shù)值的做法是比較好的。 松散耦合,還記得么?

下一行,計(jì)算當(dāng)前日期/時(shí)間,然后加上適當(dāng)?shù)男r(shí)數(shù)。 在current_datetime視圖中,我們已經(jīng)見過datetime.datetime.now()。這里新的概念是執(zhí)行日期/時(shí)間的算術(shù)操作。我們需要?jiǎng)?chuàng)建一個(gè)datetime.timedelta對(duì)象和增加一個(gè)datetime.datetime對(duì)象。 結(jié)果保存在變量dt中。

這一行還說明了,我們?yōu)槭裁丛趏ffset上調(diào)用int()——datetime.timedelta函數(shù)要求hours參數(shù)必須為整數(shù)類型。

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

在完成視圖函數(shù)和URL配置編寫后,啟動(dòng)Django開發(fā)服務(wù)器,用瀏覽器訪問http://127.0.0.1:8000/time/plus/3/ 來確認(rèn)它工作正常。 然后是 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/ 來檢驗(yàn)URL配置里設(shè)置的模式是否只 接受一個(gè)或兩個(gè)數(shù)字;Django會(huì)顯示一個(gè) Page not found error 頁(yè)面, 和以前看到的 404 錯(cuò)誤一樣。 訪問URL http://127.0.0.1:8000/time/plus/ (沒有 定義時(shí)間差) 也會(huì)拋出404錯(cuò)誤。

Django 漂亮的出錯(cuò)頁(yè)面

花幾分鐘時(shí)間欣賞一下我們寫好的Web應(yīng)用程序,然后我們?cè)賮砀泓c(diǎn)小破壞。 我們故意在 views.py 文件中引入一項(xiàng) Python 錯(cuò)誤,注釋掉 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)

啟動(dòng)開發(fā)服務(wù)器,然后訪問 /time/plus/3/ 。你會(huì)看到一個(gè)包含大量信息的出錯(cuò)頁(yè),最上面 的一條 TypeError信息是: "unsupported type for timedelta hours component:  unicode" .

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

這個(gè)例子是為了展示 Django 的出錯(cuò)頁(yè)面。 我們來花些時(shí)間看一看這個(gè)出錯(cuò)頁(yè),了解一下其中 給出了哪些信息。

以下是值得注意的一些要點(diǎn):

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

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

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

不知道你是不是那種使用小心放置的 print 語(yǔ)句來幫助調(diào)試的程序員? 你其實(shí)可以用 Django 出錯(cuò)頁(yè)來做這些,而不用 print 語(yǔ)句。 在你視圖的任何位置,臨時(shí)插入一個(gè) assert False 來觸發(fā)出錯(cuò)頁(yè)。 然后,你就可以看到局部變量和程序語(yǔ)句了。 這里有個(gè)使用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 代碼的內(nèi)部結(jié)構(gòu)以及 Django 配置,在 Internet 上公開這信息是很愚蠢的。 不懷好意的人會(huì)嘗試使用它攻擊你的 Web 應(yīng)用程序,做些下流之事。 因此,Django 出錯(cuò)信息僅在 debug 模式下才會(huì)顯現(xiàn)。 我們稍后 說明如何禁用 debug 模式。 現(xiàn)在,你只要知道 Django 服務(wù)器在你開啟它時(shí)默認(rèn)運(yùn)行在 debug 模式就行了。 (聽起來很熟悉? 頁(yè)面沒有發(fā)現(xiàn)錯(cuò)誤,如前所述,工作正常。)

下一章

目前為止,我們已經(jīng)寫好了視圖函數(shù)和硬編碼的HTML。 在演示核心概念時(shí),我們所作的是為了保持簡(jiǎn)單。但是在現(xiàn)實(shí)世界中,這差不多總是個(gè)壞主意。

幸運(yùn)的是,Django內(nèi)建有一個(gè)簡(jiǎn)單有強(qiáng)大的模板處理引擎來讓你分離兩種工作: 下一章,我們將學(xué)習(xí)模板引擎。

關(guān)閉
程序員人生
主站蜘蛛池模板: 国产精品女上位在线观看 | 欧美jizzhd欧美精品巨大 | 久久h视频 | 91精品推荐 | 亚洲综合日韩中文字幕v在线 | 大杳蕉伊人狼人久久一本线 | 91精品成人免费国产片 | 欧美亚洲日本一区二区三区浪人 | 99精品国产美女福到在线不卡 | 青草青青产国视频在线 | 九九精品视频在线播放8 | 欧美一级毛片不卡免费观看 | 欧美xxxx做受视频 | 午夜啪啪网站 | 日本午夜视频在线 | 一区二区三区四区五区 | 欧美图片小说 | 欧美三级真做在线观看 | 精品亚洲视频在线 | 国产精品ⅴ视频免费观看 | 日韩大片免费看 | 美女毛片网站 | 欧美日韩三 | 一级在线毛片 | 五月天综合 | 真实国产乱人伦在线视频播放 | 狂野欧美性猛交xxxx | 国产亚洲图片 | 中文字幕动漫精品专区 | 国产精品久久久久久久久久久威 | 真人肉体一级毛片 | 欧美日本一区二区三区道 | 精品亚洲综合久久中文字幕 | 国产高清在线免费观看 | 综合久久久久久久 | 亚洲专区欧美专区 | www.九色| 可以看的毛片网站 | 国农村精品国产自线拍 | 欧美成人一级毛片 | 精品精品国产高清a毛片牛牛 |