高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

網址設定

Model的部份看過之後,接著介紹Django很重要的一個單元,就是怎麼在Django裡設定或設計你網站內的網址。

以前你可以會看到像這樣的網址:

http://www.eddie.com.tw/book/index.php?id=100

網址後面接問號又接了一些參數,從網址大概猜得出來這應該是編號(id)第100號的書。這樣的做法不是不好,只是近年來有更好的做法,而且對SEO(Search Engine Optimization)有一些加分的效果:

http://www.eddie.com.tw/book/100

這該怎麼做呢? 在Django的網址設定是交給一個叫做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 patterns, include, url

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

urlpatterns = patterns('',
  # Examples:
  # url(r'^$', 'bookstore.views.home', name='home'),
  # url(r'^bookstore/', include('bookstore.foo.urls')),

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

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

urls.py的主要功能,就是設定"當遇到某個網址的request的時候,請找指定的App裡的View的action處理"。設定網址的對應,可能會需要學一些簡單的Regular Expression語法。

我們先來設定一下整個網站的首頁,讓它交給books/views.py裡的index方法處理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.conf.urls.defaults import patterns, include, url

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

urlpatterns = patterns('',
    # Examples:
    url(r'^$', 'bookstore.book.views.index'),
    url(r'^books/(?P<book_id>\d+)/$', 'bookstore.book.views.detail'),
    # url(r'^bookstore/', include('bookstore.foo.urls')),

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

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

其中這行:

url(r'^$', 'bookstore.book.views.index'),

表示「當遇到網址後面沒接東西的時候(也就是大家俗稱的"首頁"),請找book/views.py裡面的index方法處理」,前面的bookstore是整個專案的名稱。設定完之後如果你直接連網址http://127.0.0.1:8000/的話,會看到這個畫面:

image

跳出了ViewDoesNotExist的錯誤訊息了。看到錯誤訊息不用擔心,通常錯誤訊息裡都會跟你說哪邊有錯。原來是我們剛剛把首頁指向之後,但並沒有在對應的地方加上index方法,所以請打開book/views.py,加上index方法:

1
2
3
4
5
6
7
from django.http import HttpResponse

def index(request):
  return HttpResponse("Hello BookStore!")

def detail(request, book_id):
  return HttpResponse("Book ID = %s" % book_id)

存檔後再回來看,你應該就可以看到這個畫面:

image

如果你這樣設定:

url(r'books\.php', 'bookstore.book.views.index'),

這表示當你連到http://127.0.0.1:8000/books.php的時候,會把request丟給book/views.pyindex方法處理。看起來好像是PHP,但其實不是。二、三年前我就曾經用Django做過幫Microsoft做過某個網路行銷活動案,客戶沒有規定要用什麼程式語言(只要會動就好),不過為了讓客戶覺得我是用ASP.NET開發的,我還特地在urls.py加上.aspx的附檔名。

是有點蠢,不過也挺有趣的不是嗎? :)

接下來,我們再來看看這行:

url(r'^books/(?P<book_id>\d+)/$', 'bookstore.book.views.detail'),

意思就是說當遇到http://127.0.0.1:8000/books/100的網址的時候,那個100會被當做book_id傳給book/views.pydetail方法當做參數。

views.py裡的方法,通常我們會稱它叫做action,每個action方法的第一個參數,一定都是http request,每個action的回傳值,一定要是一個HttpResponseviews.py在一般的MVC架構裡,大概就是Controller之類的角色。

如果你有注意到在urls.py裡的這行註解,長得跟我們寫的不太一樣:

url(r'^bookstore/', include('bookstore.foo.urls')),

這其實是另一種url的設定,雞蛋不一定要放在同一個籠子裡。當你的專案如果小的時候,全部放在專案根目錄的urls.py是沒問題的(中央集權),但隨著功能越加越多,你的網址對應可能會越來越多、越來越複雜,這時候你可以在App裡自己建一個urls.py,然後把所有跟這個App有關的url"委任"給它管理(地方自治),不過這部份的細節就不再多說明,還請再參考官網文件URL dispatcher

即使我們會設定網址了,會寫對應的action了,但還是少了什麼.. 如果設計師拿一個切好版的HTML + CSS給我,難到我要像這樣用HttpResponse整個把它印出來? 當然不是,接著我們來看看在Django的MTV架構裡的T,Template!

Comments