視圖和URL配置

一、視圖

    在mysite/misite(和__init__.py一個目錄)中,創建一個view.py文件:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello,World!")

    每個視圖函數至少要有一個參數,通常被叫作request。 這是一個觸發這個視圖、包含當前Web請求信息的對象,是類django.http.HttpRequest的一個實例。在這個示例中,雖然不用request做任何事情,然而它仍必須是這個視圖的第一個參數。一個視圖就是Python的一個函數。這個函數第一個參數的類型是HttpRequest;它返回一個HttpResponse實例。爲了使一個Python的函數成爲一個Django可識別的視圖,它必須滿足這兩個條件。

    執行 django-admin.py startproject 時,該腳本會自動建立一份 URLconf(即 urls.py 文件):

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

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

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

    對urls.py文件做了兩處修改:

  1. 從模塊 (在 Python 的 import 語法中, mysite/views.py 轉譯爲mysite.views ,mysite稱爲包) 中引入了hello 視圖。
  2. 爲urlpatterns加上一行:(‘^hello/$’, hello),這行被稱作URLpattern,它是一個Python的元組。元組中第一個元素是模式匹配字符串(正則表達式);第二個元素是那個模式將使用的視圖函數。

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


Django在檢查URL模式前,移除每一個申請的URL開頭的斜槓(/)。 這意味着爲/hello/寫URL模式不用包含斜槓(/)。如果有人申請訪問/hello(尾部沒有斜槓/)會怎樣。 因爲URL模式要求尾部有一個斜槓(/),那個申請URL將不匹配。 然而,默認地,任何不匹配或尾部沒有斜槓(/)的申請URL,將被重定向至尾部包含斜槓的相同字眼的URL。 (這是受配置文件setting中APPEND_SLASH項控制的)。


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

二、Django是如何處理請求的

一切都從settings.py開始。運行python manage.py runserver後,腳本將在於manage.py同一個目錄下查找名爲settings.py的文件。這個文件包含了所有有關這個Django項目的配置信息,均大寫: TEMPLATE_DIRS , DATABASE_NAME, 等. 最重要的設置是ROOT_URLCONF,它將作爲URLconf告訴Django在這個站點中那些Python的模塊將被用到。當運行python manage.py run server後,生成的settings.py文件中的ROOT_URLCONF指向自動生成的urls.py文件,settings.py文件中會有ROOT_URLCONF=’mysite.urls‘這樣一行語句。當訪問 URL /hello/ 時,Django 根據ROOT_URLCONF 的設置裝載 URLconf 。 然後按順序逐個匹配URLconf裏的URLpatterns,直到找到一個匹配的。 當找到這個匹配 的URLpatterns就調用相關聯的view函數,並把HttpRequest 對象作爲第一個參數。

總結如下:
  1. 轉入/hello/請求
  2. Django根據ROOT_CONF來決定根URLCONF
  3. Django根據在URLCONF中的所有URL模式中,查找第一個匹配/hello/的條目
  4. 如果找到匹配,將調用相應的視圖函數
  5. 視圖函數返回一個HttpResponse對象
  6. Django把HttpResponse轉換成合適的http response,在網頁中顯示出來。

三、動態視圖

構建一個顯示時間的/time/網頁,相應的view函數進行了修改:

在URL的匹配條目中添加('^time/$',current_time)後,顯示結果如下:



四、動態URL

在 大多數動態web應用程序,URL通常都包含有相關的參數。創建第三個視圖來顯示當前時間和加上時間偏差量的時間,設計是這樣的: /time/plus/1/ 顯示當前時間+1個小時的頁面 /time/plus/2/ 顯示當前時間+2個小時的頁面 /time/plus/3/ 顯示當前時間+3個小時的頁面,以此類推。

之前用PHP的時候可能會用到查詢字符串參數, 就像/time/plus?hours=3這樣,偏差小時在查詢字符串中被參數hours指定(問號後面的是參數)。但是Django的一個核心理念就是URL必須看起來漂亮。 URL/time/plus/3/ 更加清晰, 更簡單,也更有可讀性,可以很容易的大聲念出來,因爲它是純文本,沒有查詢字符串那麼 複雜。 漂亮的URL就像是高質量的Web應用的一個標誌。Django的URL配置系統可以使你很容易的設置漂亮的URL。

使用通配符來匹配任意數量的時差
urlpatterns = patterns('',
    # ...
    (r'^time/plus/(\d+)/$', hours_ahead),
    # ...
)

這個URL模式將匹配類似 /time/plus/2/ ,/time/plus/25/ ,甚至 /time/plus/100000000000/ 的任何URL。

hous_ahead代碼:

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)

需要注意的有兩點:
  1. offset 是從匹配的URL裏提取出來的。 例如:如果請求URL是/time/plus/3/,那麼offset將會是3;如果請求URL是/time/plus/21/,那麼offset將會是21。請注意:捕獲值永遠都是字符串(string)類型,而不會是整數(integer)類型,即使這個字符串全由數字構成(如:“21”)。
這裏offset的名字可以隨意命名,但是位置必須在hours_ahead的第二個參數,urls中的正則表達式會產生group,第二個參數會自動匹配到相應的group.

結果示例圖:


P.S:
  1. 注意鬆耦合:模塊化後,模塊之間的修改儘量不相互影響,這樣比較好進行維護。
  2. 之前一直放置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)

結果如下:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章