import MySQLdb
print "Content-Type: text/html"
print "<html><head><title>Books</title></head>"
print "<body>"
print "<h1>Books</h1>"
print "<ul>"
connection = MySQLdb.connect(user="me", passwd="letmein", db="my_db")
cursor = connection.cursor()
cursor.execute("SELECT name FROM books ORDER BY pub_date DESC LIMIT 10")
for row in cursor.fetchall():
print "<li>%s</li>" % row[0]
print "</ul>"
print "</body></html>"
connection.close()
1代碼十分簡單。首先,根據CGI的要求輸出一行Content-Type,接下來是一個空行。再接下來是一些HTML的起始標籤,然後連線資料庫並執行一些查詢操作,獲取最新的十本書。遍歷這些書,同時生成一個 HTML的無序序列。最後,輸出HTML的結束標籤並且關閉資料庫連線。
像這樣的一次性的動態頁面,從頭寫起的方法並非一定不好。其中一點:這些代碼簡單易懂,就算是一個初起步的開發者都能讀明白這16行的Python代碼,而且這些代碼從頭到尾做了什麼都能了解得一清二楚。不需要學習額外的背景知識,沒有額外的代碼需要去了解。同樣,也易於部署這16行代碼,只需要將它保存為一個 latestbooks.cgi 的檔案,上傳到Web伺服器上,通過瀏覽器訪問即可。
但是,一個Web套用要遠複雜於以上情況,這種方法很快會失效,而且你將會要面對很多問題:
當多個動態頁面需要同時連線資料庫時,將會發生什麼?當然,連線資料庫的代碼不應該同時存在於各個獨立的CGI腳本中,所以最踏實的做法是把這些代碼重新組織到一個公共函數裡面。
一個開發人員 確實 需要去關注如何輸出Content-Type以及完成所有操作後去關閉資料庫么?此類問題只會降低開發人員的工作效率,增加犯錯誤的幾率。那些初始化和釋放相關的工作應該交給一些通用的框架來完成。1
如果這樣的代碼被重用到一個複合的環境中會發生什麼?每個頁面都分別對應獨立的資料庫和密碼嗎?從這點看來,就需要一些環境相關的配置檔案。
如果一個Web設計師,完全沒有Python開發經驗,但是又需要重新設計頁面的話,又將發生什麼呢?理想的情況是,頁面顯示的邏輯與從資料庫中讀取書本紀錄分隔開,這樣 Web設計師的重新設計不會影響到之前的業務邏輯。
以上正是Web框架致力於解決的問題。Web框架為應用程式提供了一套程式框架,這樣你可以專注於編寫清晰、易維護的代碼,而無需從頭做起。簡單來說,這就是DJANGO所能做的。
MVC 設計模式讓我們來研究一個簡單的例子,通過該實例,你可以分辨出,通過Web框架來實現的功能與之前的方式有何不同。下面就是通過使用Django來完成以上功能的例子:
# models.py (the database tables)
from django.db import models
class Book(models.Model):
name = models.CharField(maxlength=50)
pub_date = models.DateField()
# views.py (the business logic)
from django.shortcuts import render_to_response
from models import Book
def latest_books(request):
book_list = Book.objects.order_by('-pub_date')[:10]
return render_to_response('latest_books.html', {'book_list': book_list})
# urls.py (the URL configuration)
from django.conf.urls.defaults import *
import views
urlpatterns = patterns('',
(r'latest/$', views.latest_books),
)
# latest_books.html (the template)
<html><head><title>Books</title></head>
<body>
<h1>Books</h1>
<ul>
{% for book in book_list %}
<li>{{ book.name }}</li>
{% endfor %}
</ul>
</body></html>
4先不要擔心這個東西是 如何 工作的,我們主要是先想讓你知道總體的設計,這裡關鍵要注意的是 分離問題
models.py 檔案主要用一個 Python 類來描述數據表。稱為 模型(model) 。運用這個類,你可以通過簡單的 Python 的代碼來創建、檢索、更新、刪除資料庫中的記錄而無需寫一條又一條的SQL語句。
view.py 檔案的 latest_books() 函式中包含了該頁的業務層邏輯。這個函式叫做 視圖(view) 。
urls.py 指出了什麼樣的 URL 調用什麼的視圖,在這個例子中 /latest/ URL 將會調用 latest_books() 這個函式2
latest_books.html 是 html 模板,它描述了這個頁面的設計是如何的。
這些部分鬆散的組合在一起就是模型-視圖-控制器(MVC)的設計模式。簡單的說, MVC 是一種軟體開發的方法,它把代碼的定義和數據訪問的方法(模型)與請求邏輯(控制器)還有用戶接口(視圖)分開來。
這種設計模式關鍵的優勢在於各種組件都是 鬆散結合 的。這樣,每個由 Django驅動的Web套用都有著明確的目的,並且可獨立更改而不影響到其它的部分。比如,開發者更改一個應用程式中的 URL 而不用影響到這個程式底層的實現。設計師可以改變 HTML 頁面的樣式而不用接觸 Python 代碼。資料庫管理員可以重新命名數據表並且只需更改一個地方,無需從一大堆檔案中進行查找和替換。
本書中,每個組件都有它自己的一個章節。比如,第三章涵蓋了視圖,第四章是模板,而第五章是模型。同時第五章也深入討論了 Django 的 MVC 思想。
django 歷史在我們討論代碼之前我們需要先了解一下 Django 的歷史。知道了一些歷史知識有助於理解為什麼 Django 要建立這個框架,因為這些歷史有助於理解Django為何會這樣運作。1
如果你曾編寫過網路應用程式。那么你很有可能熟悉之前我們的 CGI 例子。傳統的網路開發人員的開發流程是這樣的:1
從頭開始編寫網路應用程式。
從頭編寫另一個網路應用程式。
從第一步中總結(找出其中通用的代碼),並運用在第二步中。
重構代碼使得能在第 2 個程式中使用第 1 個程式中的通用代碼。
重複 2-4 步驟若干次。
意識到你發明了一個框架。
這正是為什麼 Django 建立的原因!
Django 是從真實世界的套用中成長起來的,它是由 堪薩斯(Kansas)州 Lawrence 城中的一個網路開發小組編寫的。它誕生於 2003 年秋天,那時 Lawrence Journal-World 報紙的程式設計師 Adrian Holovaty 和 Simon Willison 開始用 Python 來編寫程式。當時他們的 World Online 小組製作並維護當地的幾個新聞站點, 並在以新聞界特有的快節奏開發環境中逐漸發展. 這些站點包括有 LJWorld.com、Lawrence.com 和 KUsports.com, 記者(或管理層)要求增加的特徵或整個程式都能在計畫時間內快速的被建立,這些時間通常只有幾天或幾個小時。因此為了需要,Adrian 和 Simon 開發了一種節省時間的網路程式開發框架,這是在截止時間前能完成程式的唯一途徑。
2005 年的夏天,當這個框架開發完成時,它已經用來製作了很多個 World Online 的站點。當時 World Online 小組中的 Jacob Kaplan-Moss 決定把這個框架發布為一個開源軟體。他們在 2005 年的 7 月發布並取名為 Django,來源於一個著名的爵士樂吉他演奏家 Django Reinhardt。
雖然現在 Django 是一個全世界開發者參與的開源項目,但原始的 World Online 開發者們仍然提供主要的指導來促進這個框架的成長。 World Online 還有其它方面的重要貢獻,比如雇員時間、市場材料以及框架的 Web 網站的主機和頻寬(http://www.djangoproject.com/)。
這些歷史都是相關聯的,因為她們幫助解釋了很重要的亮點。第一,Django最可愛的地方,因為Django誕生於一個全新的環境,她提供了很多的功能(特別是她的管理接口,見第6章),特別適合提供內容的網站,例如eBay, craigslist.org和washingtonpost.com,提供一種基於資料庫的動態網站。(不要看到這就感到沮喪,儘管Django擅長於動態內容管理系統,但並不表示Django主要的目的就是用來創建動態內容的網站。 某些方面 特別高效 與其他方面 不高效 是有區別的)
第二,Django的起源造就她的開源社區,因為Django來自於真實世界中的代碼,而不是來自於一個科研項目或者商業產品,她主要集中力量來解決Web開發中遇到的問題,同樣也是Django的開發者經常遇到的問題。這樣,Django每天在現有的基礎上進步。框架的開發者對於為開發人員節省開發時間具有極大的興趣,編寫更加容易維護的程式,同時保證程式運行的效率。開發人員自我激勵,儘量的節省時間和享受他們的工作(To put it bluntly, they eat their own dog food.)