本文為翻譯文章,內容請搭配 Django 1.3 版使用。
原文出處為 https://docs.djangoproject.com/en/1.3/intro/tutorial01/

讓我們從範例開始吧。

透過這個教學將讓你體驗如何從頭到尾建立一個簡單的投票程式。

這個程式會包括兩部分:

  • 一個可以讓人瀏覽、投票的公開網站。
  • 一個管理後台,讓你可以新增、修改、刪除投票項目。

在此假設你已經安裝好 Django 了。你也可以在 Python 互動 Django 是在 Python 互動環境 (interactive interpreter) 中輸入 import django。如果指令成功執行、沒有發生任何錯誤,那麼 Django 就安裝好囉。

如何取得協助:

如果你在練習過程中遇到任何障礙,請到 django-users 發文、或在 irc.freenode.net 的 #django 頻道與其他 Django 使用者討論,也許有人能幫得上忙。

 

 

建立新專案

如果這是你首次使用 Django,你得先瞭解一些初始化的步驟。也就是說,你需要自動產生一些建立 Django 專案的程式碼,這些程式碼是一堆 Django 設定的集合,包括了資料庫設定、Django 本身的設定選項以及應用程式的相關設定。

透過命令列的 cd 指令切換到你儲存程式的資料夾,接著執行指令 django-admin.py startproject mysite。這將在你所在的資料夾建立 mysite 資料夾。

不同版本的指令也許會有所不同

如果你透過各版本的 Linux 套件管理員(例如 apt-get 或 yum)安裝 Django,django-admin.py 也許會換個名字叫作 django-admin。在這份文件後續出現的每個指令你可以省略掉 .py

Mac OS X 權限

如果你用的是 Mac OS X,當你試著要執行 django-admin.py startproject 時,你也許會看到「權限不足 (permission denied)」的訊息。這是因為在像 OS X 這樣的 Unix 系統中,檔案在執行之前必須被標記為「可執行的 (executable)」。進行這個設定的方式是,打開 Terminal.app,並瀏覽(使用 cd 指令)找出 django-admin.py 安裝的資料夾,接著執行指令 chomd +x django-admin.py

備註

你得避免專案名稱和在 Python 內建元件或 Django 元件撞名。這更意味著你應該避免使用像 django(這會和 Django 本身衝突)或是 test(會和 Python 內建套件衝突)這樣的命名。

如果你透過 python setup.py 安裝 Django,那麼 django-admin.py 應該在你的系統路徑上。如果它不在你的目錄裡,你可以在 site-packages/django/bin 找到('site-packages' 是你的 Python 所安裝的目錄)。考慮在像 /usr/local/bin 之類的地方將你的路徑指向 (symlinking) django-admin.py

這些程式碼該放在哪?

如果你學過 PHP,你也許會習慣把程式碼放在網站伺服器的文件根目錄(比方說 /var/www)。不過在 Django 你就不用這樣做了。把什麼 Python 原始碼都扔上你的網站伺服器文件根目錄,可不是什麼好主意,因為這可能造成別人可能在網站上瀏覽你的原始碼的風險。就安全考量來看這可不太妙。
把你的原始碼放在某個不在文件根目錄的資料夾,比方說 /home/mycode

我們來看看 startproject 建立了些什麼:

mysite/
    __init__.py
    manage.py
    settings.py
    urls.py

這些檔案分別是:

  • __init__.py: 一個空白檔案,告訴 Python 這個目錄應該被視為是 Python 套件。(如果你是個 Python 初學者,可以閱讀 Python 官方文件,瞭解更多有關於套件的資訊。)
  • manage.py: 一個命令列工具,讓你能以不同方式與這個 Django 專案互動。你可以在 django-admin.py and manage.py 閱讀所有關於 manage.py 的細節。
  • settings.py: 這個 Django 專案的設定、配置。Django settings 說明了這個設定檔的運作方式。
  • urls.py: 這個 Django 專案的 URL 宣告;是你的 Django 網站的「目錄」。你可以在 URL dispatcher 取得更多與 URL 相關的資訊。

開發伺服器

讓我們來驗證一下它可以運作吧。切換到 mysite 資料夾(如果你還沒切過去),然後執行指令 python manage.py runserver。你可以看到命令列視窗出現下列輸出:

Validating models...
0 errors found.

Django version 1.0, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

你已經啟動了 Django 開發伺服器,這是個完全以 Python 撰寫的輕量型網站伺服器。Django 開發團隊把它包進 Django 裡頭,這麼一來你就可以快速開發,在你準備要上線之前都不必去設定正式主機的設定(像 Apache)。

這是個提醒你的好時機──千萬別在任何正式上線環境使用類似這樣的伺服器。僅限開發使用。(Django 開發團隊設計的是一個網站框架,可不是網站伺服器噢。)

現在伺服器開始運作啦,從你的瀏覽器看看 http://127.0.0.1:8000/。你會看到一個甜美輕柔的淡藍色 "Welcome to Django" 頁面。開發伺服器正常運作囉!

改變埠號 (port)

預設的情況下,runserver 指令會在內部 IP 的 8000 port 啟動開發伺服器。
如果你想改變伺服器埠號,就把埠號加進去命令列參數裡。比方說呢,下列指令會啟動一個在 8080 port 上的伺服器:
python manage.py runserver 8080
如果你想改變伺服器 IP,就把 IP 和 port 寫在一起。如果要讓所有 public IP 可以連上來(如果你要在其他電腦上顯示你的成果時會用得到),就這樣做:
python manage.py runserver 0.0.0.0:8000
完整的開發伺服器文件請參考 runserver 一節。

資料庫設定

現在來編輯 settings.py。這是個一般的 Python 模組,以模組級變數 (module-level variables) 呈現 Django 設定值。改變 DATABASES'default' 項目中的下列值,以符合你的資料庫連線設定:

  • ENGINE -- 可以是 'django.db.backends.postgresql_psycopg2', 'django.db.backends.mysql' 或 'django.db.backends.sqlite3'. 其他後端也行得通。
  • NAME -- 你的資料庫名稱。如果你使用 SQLite,資料庫會是你電腦上的一個檔案;在這種情況下,NAME 應該是資料庫檔案的完整的絕對路徑(包括檔名)。如果該檔案不存在,它會在你第一次同步資料庫時一併自動建立。(詳見後續說明)
    在設定路徑時,一定要用斜線,即使是在 Windows 上也是一樣。(例如:C:/homes/user/mysite/sqlite3.db)
  • USER -- 你的資料庫使用者名稱(SQLite 不必設)。
  • PASSWORD -- 你的資料庫密碼(SQLite 不必設)。
  • HOST -- 你的資料庫主機。若你的資料庫伺服器是安裝在同一台實體機器上,這個設定就保持空白(SQLite 不必設)。

如果你是個資料庫新手,我們會建議你用 SQLite(ENGINE 設定為 'django.db.backends.sqlite3')。SQLite 內建於 Python 2.5 與其之後更新的版本,你就不用再安裝任何東西。

備註

如果你用的是 PostgreSQL 或 MySQL,在此要確認你已經建立了資料庫。在你的資料庫互動介面裡,執行 "CREATE DATABASE database_name;" 以建立資料庫。
如果你用的是 SQLite,你不必事先建立任何東西──資料庫檔案會在必要時自動建立。 

當你編輯 settings.py 時,留意一下檔尾的 INSTALLED_APPS 設定。這變數包括了所有位於目前 Django 實體中的 Django 應用程式的名稱。應用程式可以在多個專案裡使用,你可以打包、發佈這些應用程式給其他人,讓其他人能在他們的專案裡使用。

預設情況下,INSTALLED_APPS 包括了下列應用程式(皆由 Django 提供):

一般情況下,預設環境都附有這些應用程式。

每一個應用程式都用到至少一個資料表,所以我們得在用到這些應用程式前先在資料庫建立這些資料表。為了完成這項前置作業,我們執行下列指令:

python manage.py syncdb

syncdb 指令根據 INSTALLED_APPS 設定與你的 settings.py 設定,建立所有必備的資料表。你會看到每個資料表建立完成的訊息,也會有提示訊息詢問你是否要建立認證系統中的 superuser 帳戶。依序完成這些事。

如果你有興趣的話,你可以執行你的資料庫的命令列工具,並輸入 \dt (PostgreSQL)、SHOW TABLES (MySQL)、.shema (SQLite) 列出 Django 建立的資料表。

簡化

如同先前提過的,一般在預設情況下都自動引用了應用程式,不過不是每個人都用得到這些東西。如果你用不著它們,可以在執行 syncdb 之前,隨時註解掉或刪除 syncdb 指令只建立 INSTALLED_APPS 裡頭的應用程式所需的資料表。

建立模組

現在你的環境(一個「專案」)已經建置好囉,你已經準備好開工啦。

每個你撰寫的 Django 應用程式由 Python 套件(位於某個你的 Python 路徑上)組成,遵循一定的規範。Django 本身有個功能,可以自動產生基本的應用程式資料夾結構,所以你只要專心寫你的程式碼就好,不必管要開哪些目錄。

專案 (Projects) vs. 應用程式 (apps)

專案和應用程式有什麼不同呢?一個應用程式就是一個處理某些事的網頁應用程式,比方說部落格、簡易投票應用程式的公開記錄資料庫……等等;一個專案是特定網站的設定值與應用程式的集合。專案包括了許多的應用程式;應用程式可以身處於多個專案之中。

你的應用程式可以放在 Python 路徑上的任何地方。在這份教學裡,我們將我們的投票應用程式建立在 mysite 資料夾。

確認你已位於 mysite 資料夾後,輸入下列指令來建立你的應用程式:

python manage.py startapp polls

這樣就建立了一個 polls 資料夾,結構長成這樣:

polls/
    __init__.py
    models.py
    tests.py
    views.py

這個目錄結構就是用來儲存投票程式的。

撰寫 Django 資料庫網站應用程式的第一步就是定義你的模組──也就是你的資料庫架構以及其中的詮釋資料 (metadata)。

原理

你的資料唯一且明確的資料來源就是模組 (model)。包括你的資料儲存時的必要欄位與行為。Django 依循 DRY 準則。其目的是在某個地方定義你的資料模組,並透過這個模組自動產生一些東西。

在我們的簡易型投票程式裡,我們會建立兩個模組:投票 (polls) 與選項 (choices)。投票包括了問題與公告日期;選項包括兩個欄位:選項的描述文字與得到的合計票數。每個選項都和投票相關。

這些概念可以由簡單的 Python 類別實現。編輯 polls/models.py 檔案,內容如下:

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()

原始碼很簡單。每個模組都是 django.db.models.Model 這個類別的子類別。每個模組都有一些它自己的類別變數,每個模組裡的類別變數又都能對應到資料庫的特定欄位。

每個欄位以欄位類別實體表示──比方說,CharField 是字元欄位,DateTimeField 是日期與時間欄位。這會讓 Django 知道每個欄位裡保存了什麼類別的資料。

每個欄位實體的名稱(例如:questionpub_date)就是欄位的名稱,以機讀格式儲存。你可以在 Python 原始碼裡使用這些值,你的資料庫會取用它們作為欄位名稱。

你可以利用第一個選填參數指定一個可供人工判讀的名稱。它用在 Django 的一對內省部分 (introspective parts),也兼作為說明文件之用。如果這個欄位未設定,Django 會使用機讀名稱。在這個範例裡,我們只定義了人工判讀的名稱 Poll.pub_date。對這個模組裡的其他部分而言,這部分的機讀名稱就足以作為人工判讀名稱了。

部分欄位類別有其必要元素。比方說,CharField 必須給定一個 max_length。它不僅用在資料庫結構,還用在驗證,我們後面也會談到。

最後,請留意使用外鍵定義的關係。這讓 Django 知道每個 Choice 會和一個 Poll 產生關聯。Django 支援所有常見資料庫的關聯模式:多對一、多對多、一對一。

啟用模組

這一小段模組程式碼卻給了 Django 大量的訊息。有了它,Django 可以:

  • 建立這支應用程式的資料庫結構(CREATE TABLE 語法)。
  • 建立取用 Poll 與 Choice 物件的 Python database-access API。

但我們得先讓專案知道,polls 應用程式已經安裝好了。

原理

Django 應用程式是「可插拔 (pluggable)」的:你可以在多個專案中使用同一支應用程式,同時你還可以發布應用程式,因為應用程式不會被綁死在特定的 Django 安裝 (installation) 裡。

再次編輯 settings.py 這支檔案,變更 INSTALLED_APPS 的設定字串使之包括了 'polls',完成設定後的內容如下:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'polls'
)

現在 Django 已經得知 polls 應用程式被引用了。我們再執行另一個指令:

python manage.py sql polls

你應該可以看到類似以下的內容(用來建立 polls 應用程式的 CREATE TABLE SQL 語法):

BEGIN;
CREATE TABLE "polls_poll" (
    "id" serial NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
    "choice" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
COMMIT;

請注意以下幾點:

  • 實際的輸出取決於你所使用的資料庫。
  • 資料表名稱是根據應用程式 (polls) 的名稱與小寫的模組名稱 (poll, choice) 自動產生的。(你可以改寫這個行為)
  • 主鍵 (ID) 是自動加上去的。(你也可以改寫這個行為)
  • 依慣例,Django 會在外鍵欄位的名稱加上 "_id"。當然啦,你也可以改寫這行為。
  • 外鍵關聯是由 REFERENCES 語句明確宣告。
  • 這是針對你正在使用的資料庫,所以資料庫的特有欄位類別,例如 auto_increment (MySQL), serial (PostgreSQL), 或 integer primary key (SQLite) 都會自動為您處理好。引用欄位名稱時也是自動為您處理好(例如:應該使用雙引號或單引號)。這個教學的作者使用的是 PostgreSQL,所以範例輸出的就是 PostgreSQL 語法。
  • SQL 指令並未實際在你的資料庫中執行──這只是把結果印出在螢幕上,讓你看看 Django 認為怎樣的 SQL 是必要的。如果你要執行這些 SQL,你得把這些 SQL 複製、貼上到你的資料庫互動介面上。不過等一下我們就會看到 Django 提供了一個更簡單的方法來送交 SQL 指令給資料庫。

如果你有興趣的話,還可以執行下列指令:

檢視這些指令的輸出,有助於你瞭解在這個機制下實際上發生了什麼事。

現在,再次執行 syncdb 以便在你的資料庫裡建立那些模組的資料表:

python manage.py syncdb

syncdb 指令會根據 INSTALLED_APPS 裡的所有應用程式,找出還沒在資料庫裡建檔的應用程式,在你的資料庫上執行 'sqlall' 的 SQL 指令。這會為你上次執行 syncdb 後加入到專案裡的所有應用程式,建立所有的資料表、初始化資料與索引。你可以隨心所欲的執行 syncdb,反正它只會建立尚不存在的資料表。

閱讀 django-admin.py,可以全盤瞭解 manage.py 功能可以做哪些事。

使用 API!

現在,我們來進入 Python 互動式命令列環境、試試 Django 送你的免費 API 吧。使用下列指令來啟動 Python 命令列:

python manage.py shell

我們執行這句指令、而不是單單只輸入 "python",因為 manage.py 會為你設置系統環境。「設定環境」包括了兩件事:

  • sys.path 設定 polls。為了增加彈性,在此專案使用到的數個 Django 參照會以 Python 的點路徑 (dotted-path) 方式表示(例如:'polls.models')。為了能正常運作,polls 套件必須設在 sys.path。
    我們已經看到一個範例:INSTALLED_APPS 設定就是個以點路徑表示的套件列表。
  • 設定 DJANGO_SETTINGS_MODULE 環境變數,這變數可以讓 Django 取得你的 settings.py 檔案的路徑。

略過 manage.py

如果你不想用 manage.py,那也沒關係。只要確定 mysite 和 polls 都在 Python 路徑的根節點就好(例如:import mysiteimport polls 可正常運作無誤),同時在 mysite.settings 設定 DJANGO_SETTINGS_MODULE 環境變數。
欲知詳情請參考 django-admin.py

進入命令列模式後,瀏覽資料庫 API

>>> from polls.models import Poll, Choice # Import the model classes we just wrote.

# 目前系統裡還沒有任何的投票
>>> Poll.objects.all()
[]

# 建立一個新的 Poll
>>> import datetime
>>> p = Poll(question="What's up?", pub_date=datetime.datetime.now())

# 把物件存進資料庫。你得明確地呼叫 save()。
>>> p.save()

# 現在它有了 ID 了。記住,這也許叫作 "1L" 而不是 "1"(取決於你使用的資料庫)。
# 這也沒什麼,只代表你的資料庫後端傾向回傳 Python 長整數型態的整數。

>>> p.id
1

# 透過 Python 屬性來取得資料庫欄位。
>>> p.question
"What's up?"
>>> p.pub_date
datetime.datetime(2007, 7, 15, 12, 00, 53)

# 修改屬性值,呼叫 save()。
>>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
>>> p.save()


# objects.all() 顯示所有資料庫裡的投票資料。
>>> Poll.objects.all()
[<Poll: Poll object>]

且慢。<Poll: Poll object> 這樣的呈現結果,完全無助於瞭解物件本身。我們來改一下 polls 模組(在 polls/models.py 這個檔案裡),增加 __unicode__() 方法到 Poll 與 Choice 類別裡:

class Poll(models.Model):
    # ...
    def __unicode__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __unicode__(self):
        return self.choice

在你的模組裡加上 __unicode__() 是很重要的,不僅為了你在命令列模式裡能清楚思考,也是為了在整個 Django 自動產生的管理介面裡物件中的物件呈現著想。

為什麼用 __unicode__(),而不用 __str__()

如果你很熟 Python,你可能會習慣在你的類別裡加上 __str__() 方法、而非 __unicode__()。在這邊我們用了 __unicode__(),是因為 Django 模組預設會以 Unicode 處理。所有存在你的資料庫裡的資料都會被轉成 Unicode 後回傳。
Django 模組預設的 __str__() 方法會呼叫 __unicode__() 並將結果轉換為 UTF-8 字串陣列。也就是說呢,unicode(p) 會回傳 Unicode 字串,而 str(p) 會回傳一般字串(字串中的每個字元會編碼為 UTF-8)。
如果上述對你來說是一團亂碼,那麼只要記住在你的模組裡加上 __unicode__() 就對了。運氣好的話,一切會為了你而正常運轉的。

請注意這些都是一般的 Python 方法。我們來增加個示範用的自訂方法:

import datetime
# ...
class Poll(models.Model):
    # ...
    def was_published_today(self):
        return self.pub_date.date() == datetime.date.today()

更多 import datetime 的延伸內容,請參考 Python 標準 datetime 模組。

儲存這些變更,開啟一個新的 Python 互動視窗、再次執行 manage.py 指令:

>>> from polls.models import Poll, Choice

# 確定新增的 __unicode__()  可以正常運作
>>> Poll.objects.all()
[<Poll: What's up?>]

# Django 提供了一個完整的資料庫查找 API,完全由關鍵字參數驅動
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]

# 取得投票年份在 2007 的資料
>>> Poll.objects.get(pub_date__year=2007)
<Poll: What's up?>

>>> Poll.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Poll matching query does not exist.


# 通常會以主鍵搜尋,所以 Django 提供一個捷徑來進行主鍵明確搜尋。
# 下列內容和 Poll.objects.get(id=1) 是一樣的。

>>> Poll.objects.get(pk=1)
<Poll: What's up?>

# 確定我們的自訂方法可以正常運作。
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False

# 讓每個投票有兩個選項。create 建立了新的 choice 物件,執行 INSERT 語法,
# 增加 choice 到可選擇的選項中,並回傳一個新的 Choice 物件。
# Django 建立了一個集合來維持「另一方面」的外鍵關聯(例如:投票中的選項們),
# 可透過 API 取用。

>>> p = Poll.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> p.choice_set.all()
[]

# 建立三個 choices。
>>> p.choice_set.create(choice='Not much', votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice='The sky', votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)

# Choice 物件有方法可以取得它們相關聯的 Poll 物件。
>>> c.poll
<Poll: What's up?>

# 反之亦然,Poll 物件可以取得 Choice 物件。
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.choice_set.count()
3

# 這個 API 依你所需自動追蹤關聯。
# 使用雙下劃線切割關聯。
# 你想切幾層就幾層,沒有限制。
# 找出 pub_date 屬於 2007 年的投票的所有 Choice。

>>> Choice.objects.filter(poll__pub_date__year=2007)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# 使用 delete() 刪除一個選項
>>> c = p.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete()

想知道更多模組間的關聯,請參考 Accessing related objects。想瞭解更多如何透過 API 使用雙下劃線 (double underscores) 進行欄位查找 (field lookups),請參考 Field lookups。完整的資料庫 API 細節,請參考 Database API reference

當你熟悉了這個 API,接著來看看這個教學的第二章,讓 Django 的自動管理介面執行起來吧。

 

 

 

本文為翻譯文章,內容請搭配 Django 1.3 版使用。
原文出處為 https://docs.djangoproject.com/en/1.3/intro/tutorial01/

文章標籤

創作者介紹
創作者 fannys23 的頭像
fannys23

小攻城師的戰場筆記

fannys23 發表在 痞客邦 留言(0) 人氣()