由于Django是在一個(gè)快節(jié)奏的新聞編輯室環(huán)境下開發(fā)出來的,因此它被設(shè)計(jì)成讓普通的網(wǎng)站開發(fā)工作簡(jiǎn)單而快 捷。以下簡(jiǎn)單介紹了如何用 Django 編寫一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的Web應(yīng)用程序。
本文檔的目標(biāo)是給你描述足夠的技術(shù)細(xì)節(jié)能讓你理解Django是如何工作的,但是它并不表示是一個(gè)新手指南或參考目錄 – 其實(shí)這些我們都有! 當(dāng)你準(zhǔn)備新建一個(gè)項(xiàng)目,你可以 從新手指南開始 或者 深入閱讀詳細(xì)的文檔.
盡管你在 Django 中可以不使用數(shù)據(jù)庫(kù),但是它提供了一個(gè)完善的可以用 Python 代碼描述你的數(shù)據(jù)庫(kù)結(jié)構(gòu)的對(duì)象關(guān)聯(lián)映射(ORM)。
數(shù)據(jù)模型語法 提供了許多豐富的方法來展現(xiàn)你的模型 – 到目前為止,它已經(jīng)解決了兩個(gè)多年積累下來數(shù)據(jù)庫(kù)架構(gòu)問題。下面是個(gè)簡(jiǎn)單的例子,可能被保存為 mysite/news/models.py:
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __unicode__(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter)
def __unicode__(self):
return self.headline
下一步,運(yùn)行 Django 命令行工具來自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)表:
manage.py syncdb
syncdb 命令會(huì)查找你所有可用的模型(models)然后在你的數(shù)據(jù)庫(kù)中創(chuàng)建還不存在的數(shù)據(jù)庫(kù)表。
接著,你就可以使用一個(gè)便捷且功能豐富的 Python API 來訪問你的數(shù)據(jù)。API 是動(dòng)態(tài)生成的,不需要代碼生成:
# 導(dǎo)入我們?cè)?"news "應(yīng)用中創(chuàng)建的模型。
>>> from news.models import Reporter, Article
# 在系統(tǒng)中還沒有 reporters 。
>>> Reporter.objects.all()
[]
# 創(chuàng)建一個(gè)新的 Reporter 。
>>> r = Reporter(full_name='John Smith')
# 將對(duì)象保存到數(shù)據(jù)庫(kù)。你需要顯示的調(diào)用 save() 方法。
>>> r.save()
# 現(xiàn)在它擁有了一個(gè)ID。
>>> r.id
1
# 現(xiàn)在新的 reporter 已經(jīng)存在數(shù)據(jù)庫(kù)里了。
>>> Reporter.objects.all()
[<Reporter: John Smith>]
# 字段被表示為一個(gè) Python 對(duì)象的屬性。
>>> r.full_name
'John Smith'
# Django 提供了豐富的數(shù)據(jù)庫(kù)查詢 API。
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist. Lookup parameters were {'id': 2}
# 創(chuàng)建一個(gè) article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()
# 現(xiàn)在 article 已經(jīng)存在數(shù)據(jù)庫(kù)里了。
>>> Article.objects.all()
[<Article: Django is cool>]
# Article 對(duì)象有 API 可以訪問到關(guān)聯(lián)到 Reporter 對(duì)象。
>>> r = a.reporter
>>> r.full_name
'John Smith'
# 反之亦然:Reporter 對(duì)象也有訪問 Article 對(duì)象的API。
>>> r.article_set.all()
[<Article: Django is cool>]
# API 會(huì)在幕后高效的關(guān)聯(lián)表來滿足你的關(guān)聯(lián)查詢的需求。
# 以下例子是找出名字開頭為 "John" 的 reporter 的所有 articles 。
>>> Article.objects.filter(reporter__full_name__startswith="John")
[<Article: Django is cool>]
# 通過更改一個(gè)對(duì)象的屬性值,然后再調(diào)用 save() 方法來改變它。
>>> r.full_name = 'Billy Goat'
>>> r.save()
# 調(diào)用 delete() 方法來刪除一個(gè)對(duì)象。
>>> r.delete()
一旦你的 models 被定義好,Django 能自動(dòng)創(chuàng)建一個(gè)專業(yè)的,可以用于生產(chǎn)環(huán)境的 管理界面 – 一個(gè)可讓授權(quán)用戶添加,修改和刪除對(duì)象的網(wǎng)站。它使用起來非常簡(jiǎn)單只需在你的 admin site 中注冊(cè)你的模型即可。:
# In models.py...
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter)
# In admin.py in the same directory...
import models
from django.contrib import admin
admin.site.register(models.Article)
這種設(shè)計(jì)理念是你的網(wǎng)站一般是由一個(gè)員工,或者客戶,或者僅僅是你自己去編輯 – 而你應(yīng)該不會(huì)想要僅僅為了管理內(nèi)容而去創(chuàng)建后臺(tái)界面。
在一個(gè)創(chuàng)建 Django 應(yīng)用的典型工作流中,首先需要?jiǎng)?chuàng)建模型并盡可能快地啟動(dòng)和運(yùn)行 admin sites, 讓您的員工(或者客戶)能夠開始錄入數(shù)據(jù)。然后,才開發(fā)展現(xiàn)數(shù)據(jù)給公眾的方式。
一個(gè)干凈的,優(yōu)雅的 URL 方案是一個(gè)高質(zhì)量 Web 應(yīng)用程序的重要細(xì)節(jié)。 Django 鼓勵(lì)使用漂亮的 URL 設(shè)計(jì),并且不鼓勵(lì)把沒必要的東西放到 URLs 里面,像 .php 或 .asp.
為了給一個(gè) app 設(shè)計(jì) URLs,你需要?jiǎng)?chuàng)建一個(gè) Python 模塊叫做 URLconf。這是一個(gè)你的 app 內(nèi)容目錄, 它包含一個(gè)簡(jiǎn)單的 URL 匹配模式與 Python 回調(diào)函數(shù)間的映射關(guān)系。這有助于解耦 Python 代碼和 URLs 。
這是針對(duì)上面 Reporter/Article 例子所配置的 URLconf 大概樣子:
from django.conf.urls import patterns
urlpatterns = patterns('',
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
)
上面的代碼映射了 URLs ,從一個(gè)簡(jiǎn)單的正則表達(dá)式,到 Python 回調(diào)函數(shù)(“views”)所在的位置。 正則表達(dá)式通過圓括號(hào)來“捕獲” URLs 中的值。當(dāng)一個(gè)用戶請(qǐng)求一個(gè)頁面時(shí), Django 將按照順序去匹配每一個(gè)模式,并停在第一個(gè)匹配請(qǐng)求的 URL 上。(如果沒有匹配到, Django 將會(huì)展示一個(gè)404的錯(cuò)誤頁面。) 整個(gè)過程是極快的,因?yàn)樵诩虞d時(shí)正則表達(dá)式就進(jìn)行了編譯。
一旦有一個(gè)正則表達(dá)式匹配上了,Django 將導(dǎo)入和調(diào)用對(duì)應(yīng)的視圖,它其實(shí)就是一個(gè)簡(jiǎn)單的 Python 函數(shù)。每個(gè)視圖將得到一個(gè) request 對(duì)象 – 它包含了 request 的 meta 信息 – 和正則表達(dá)式所捕獲到的值。
例如:如果一個(gè)用戶請(qǐng)求了個(gè) URL “/articles/2005/05/39323/”, Django 將會(huì)這樣調(diào)用函數(shù) news.views.article_detail(request, '2005', '05', '39323').
每個(gè)視圖只負(fù)責(zé)兩件事中的一件:返回一個(gè)包含請(qǐng)求頁面內(nèi)容的 HttpResponse 對(duì)象; 或拋出一個(gè)異常如 Http404 。至于其他就靠你了。
通常,一個(gè)視圖會(huì)根據(jù)參數(shù)來檢索數(shù)據(jù),加載一個(gè)模板并且根據(jù)該模板來呈現(xiàn)檢索出來的數(shù)據(jù)。 下面是個(gè)接上例的 year_archive 例子
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
這個(gè)例子使用了 Django 的 模板系統(tǒng),該模板系統(tǒng)功能強(qiáng)大且簡(jiǎn)單易用,甚至非編程人員也會(huì)使用。
設(shè)計(jì)你的模板(templates)
上面的例子中載入了 news/year_archive.html 模板。
Django 有一個(gè)模板搜索路徑板,它讓你盡可能的減少冗余而重復(fù)利用模板。在你的 Django設(shè)置中,你可以指定一個(gè)查找模板的目錄列表。如果一個(gè)模板沒有在這個(gè) 列表中,那么它會(huì)去查找第二個(gè),然后以此類推。
假設(shè)找到了模板 news/year_archive.html 。下面是它大概的樣子:
{% extends "base.html" %}
{% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
<h1>Articles for {{ year }}</h1>
{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}
變量使用雙花括號(hào)包圍。`{{ article.headline }} 表示 “輸出 article 的 headline 屬性”。而點(diǎn)符號(hào)不僅用于表示屬性查找,還可用于字典的鍵值查找、索引查找和函數(shù)調(diào)用。
注意 {{ article.pub_date|date:"F j, Y" }}
使用了 Unix 風(fēng)格的“管道”(“|”符合)。這就是所謂的模板過濾器,一種通過變量來過濾值的方式。本例中,Python datetime 對(duì)象被過濾成指定的格式(在 PHP 的日期函數(shù)中可以見到這種變換)。
你可以無限制地串聯(lián)使用多個(gè)過濾器。你可以編寫自定義的過濾器。你可以定制自 己的模板標(biāo)記,在幕后運(yùn)行自定義的 Python 代碼。
最后,Django 使用了“模板繼承”的概念:這就是 {% extends "base.html" %}
所做的事。它意味著 “首先載入名為 ‘base’ 的模板中的內(nèi)容到當(dāng)前模板,然后再處理本模板中的其余內(nèi)容?!笨傊?,模板繼承讓你在模板間大大減少冗余內(nèi)容:每一個(gè)模板只需要定義它獨(dú)特的部分即可。
下面是使用了 靜態(tài)文件 的 “base.html” 模板的大概樣子:
{% load staticfiles %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>
簡(jiǎn)單地說,它定義了網(wǎng)站的外觀(含網(wǎng)站的 logo ),并留下了個(gè)“洞”讓子模板來填充。這使站點(diǎn)的重新設(shè)計(jì)變得非常容易,只需改變一個(gè)文件 – “base.html” 模板。
它也可以讓你創(chuàng)建一個(gè)網(wǎng)站的多個(gè)版本,不同的基礎(chǔ)模板,而重用子模板。 Django 的創(chuàng)建者已經(jīng)利用這一技術(shù)來創(chuàng)造了顯著不同的手機(jī)版本的網(wǎng)站 – 只需創(chuàng)建一個(gè)新的基礎(chǔ)模板。
請(qǐng)注意,如果你喜歡其他模板系統(tǒng),那么你可以不使用 Django 的模板系統(tǒng)。 雖然 Django 的模板系統(tǒng)特別集成了 Django 的模型層,但并沒有強(qiáng)制你使用它。同理,你也可以不使用 Django 的數(shù)據(jù)庫(kù) API。您可以使用其他數(shù)據(jù)庫(kù)抽象層,您可以讀取 XML 文件,你可以從磁盤中讀取文件,或任何你想要的方法去操作數(shù)據(jù)。 Django 的每個(gè)組成部分: 模型、視圖和模板都可以解耦,以后會(huì)談到。
這里只是簡(jiǎn)要概述了 Django 的功能。以下是一些更有用的功能:
一個(gè) 緩存框架 可以與 memcached 或其他后端緩存集成。 一個(gè) 聚合框架 可以讓創(chuàng)建 RSS 和 Atom 的 feeds 同寫一個(gè)小小的 Python 類一樣容易。 更性感的自動(dòng)創(chuàng)建管理站點(diǎn)功能 – 本文僅僅觸及了點(diǎn)皮毛。 顯然,下一步你應(yīng)該 下載 Django,閱讀 入門教程 并且加入 社區(qū). 感謝您的關(guān)注!
譯者:Django 文檔協(xié)作翻譯小組,原文:Overview。
本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。
Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。
{% endraw %}