正如我們的第一個目標,創建一個網頁,用來輸出這個著名的示例信息:
1
|
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文件:
1
2
3
4
|
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會像下面這個樣子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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中忽略被注釋的行后的實際內容
1
2
3
4
|
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功能.
1
2
3
4
5
6
|
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交互解釋器,然后輸入:
1
2
|
>>> 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頁面。