Python 3 Tutorial 第九堂(2)撰寫 Django 中第一個 View


瞭解如何使用 Django 基本的 ORM 操作之後,現在該是來撰寫第一個 View 的時候了,我們直接從練習中來瞭解如何撰寫。

練習 14:撰寫第一個 View

開啟 polls/views.py,在當中撰寫如下的程式碼:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the poll index.")

def detail(request, question_id):
    return HttpResponse("You're looking at question {id}.".format(id = question_id))

def results(request, question_id):
    return HttpResponse("You're looking at the results of question {id}.".format(id = question_id))

def vote(request, question_id):
    return HttpResponse("You're voting on question {id}.".format(id = question_id)) 

這兒的四個函式,將對應至不同的 URL 請求,目前只是簡單的作些字串顯示。每個函式的第一個參數,實際上會是 HttpRequest 實例,封裝了關於請求的相關資料,有些 URL 請求會帶有 question_id 請求參數,這可以在函式的第二個參數取得請求值。

每個 URL 請求該如何對應至函式,可以在 polls 目錄下建立一個 urls.py 檔案進行定義:

from django.conf.urls import url

from . import views

urlpatterns = [
    # ex: /polls/
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

url 的第一個參數接受規則表示式(Regular expression),用來定義 URL Pattern,第二個參數表示該對應至哪個函式,第三個參數用來定義這個 URL Pattern 的名稱,某些地方若要參考這個定義,可以透過名稱來指定參考。

如果你仔細看上頭的規則表示式定義,會發現並沒有定義 polls 前置名稱,實際上這是在 mysite 目錄中的 urls.py 定義。例如:

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
    url(r'^admin/', admin.site.urls),
]

這個 urls.py 定義了全名的 URL 對應,在上頭可以看到定義了 polls 前置名稱下,接下來的規則是包括在 polls.urls,也就是方才在 polls 目錄中定義的 urls.py 中。

完成以上定義之後,可以鍵入指令 python3.5 manage.py runserver,然後分別用瀏覽器請求不同網站,你應該會看到以下結果:

撰寫 Django 中第一個 View

Controller 還是 View?

如果你曾使用過其他的 Web MVC 框架,可能會對這個練習感到疑惑,為什麼處理請求的函式是定義在 views.py 這樣的檔案名稱之中?在其他框架中,你知道處理請求參數不都是 Controller 嗎?

就名稱上來說,哪個才是標準名稱,其實是有爭議的;不過在 Django 之中,將特定 URL 對應的回呼函式認定為 View,那麼 Django 中 Controller 是在哪邊?也許就是 Django 框架本身!

實際上,大部份 Web MVC 框架確實也都會有一些請求的前置處理,當請求到達實際的 Controller 時,對請求要進行的處理,通常就是(或最好)只剩下轉發請求給商務 Model,取得樣版(Template)引擎必要的資料 Model,然後再轉發給 View 進行呈現。

Django 或許只是在實作上更強制地彰顯了這點,或許可以這麼說,Django 其實是個 MTV 框架,也就是 Model、Template、View 框架

有些人會將 Django 與 Rails 相比較,也可能會問,在 Rails 中有 before_filter 這類方法,可以作為 Controller 處理請求前的過濾器,那麼 Django 有嗎?嗯 … 因為 Django 本身 Controller 的功能是由框架本身負擔,也因此沒有 Rails 中 before、around 與 after_ filter 的概念,如果真的要在 views.py 中的函式被呼叫前,進行某些處理,直接手工寫個裝飾器(Decorator)函式並不會太困難,或者你也可以使用現成的一些通用裝飾器,你可以參考 User authentication in Django

URLconf

Django 中呼叫哪個 view,是由 Python 的 URLconf(非正式名稱)模組來決定,這些模組是純 Python 撰寫,在 URL Pattern 與 Python 回呼函式(也就是你的 View)之間進行簡單的對應。 url 函式有兩個必要與兩個建議指定的參數:

  • regex:使用規則表示式定義的 URL Pattern。
  • view:如果 Django 發現有符合的規則表示式時,應當呼叫的特定函式,該函式第一個參數是 HttpRequest 型態,第二個之後的引數會是經由規則表示式捕捉到的值。
  • kwargs:使用 dict,可用來傳入 View 的關鍵字引數。
  • name:為 URL 定義的名稱,可作於 Django 樣版其他地方參考時使用。

如果你還不清楚規則表示式,以下作些簡單的說明,mysite/urls.py 中定義的部份,意義如下:

撰寫 Django 中第一個 View

而 polls/urls.py 中定義的部份,意義如下:

撰寫 Django 中第一個 View

接下來我們還要繼續深入 Django,像是樣版系統 …