鍍金池/ 教程/ Python/ 編寫你的第一個 Django 程序 第1部分
點擊劫持保護
安全問題歸檔
Model 類參考
將遺留數(shù)據(jù)庫整合到Django
關(guān)聯(lián)對象參考
內(nèi)建基于類的視圖的API
聚合
Django 中的用戶認證
django.contrib.humanize
Django管理文檔生成器
分頁
使用Django輸出CSV
加密簽名
文件儲存API
安全
Django中的測試
國際化和本地化
為Django編寫首個補丁
條件表達式
日志
模型元選項
部署靜態(tài)文件
執(zhí)行查詢
使用Django認證系統(tǒng)
基于類的視圖
中間件
編寫自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫訪問優(yōu)化
錯誤報告
基于類的內(nèi)建通用視圖
編寫自定義存儲系統(tǒng)
編寫你的第一個 Django 程序 第3部分
編寫數(shù)據(jù)庫遷移
使用表單
編寫你的第一個 Django 程序 第2部分
編寫你的第一個 Django 程序 第1部分
如何使用會話
系統(tǒng)檢查框架
新手入門
信號
編寫視圖
如何使用WSGI 部署
編寫你的第一個Django應用,第6部分
常見的網(wǎng)站應用工具
Widgets
內(nèi)建的視圖
模型實例參考
視圖層
Django中的密碼管理
高級教程:如何編寫可重用的應用
國際化和本地化
"本地特色"附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類)
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫函數(shù)
自定義查找
使用基于類的視圖處理表單
管理操作
開發(fā)過程
編寫你的第一個Django應用,第5部分
進行原始的sql查詢
模型層
多數(shù)據(jù)庫
編寫你的第一個 Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應用
按需內(nèi)容處理
管理器
視圖裝飾器
驗證器
使用Django輸出PDF
File對象
Django 的快捷函數(shù)
基于類的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

編寫你的第一個 Django 程序 第1部分

讓我們通過例子來學習。

在本教程中,我們將引導您創(chuàng)建一個基本的投票應用。

它將包含兩部分:

  • 一個公共網(wǎng)站,可讓人們查看投票的結(jié)果和讓他們進行投票。
  • 一個管理網(wǎng)站,可讓你添加、修改和刪除投票項目。

我們假設(shè)你已經(jīng) 安裝了 Django 。你可以運行以下命令來驗證是否已經(jīng)安裝了 Django 和運行著的版本號:

python -c "import django; print(django.get_version())"

你應該看到你安裝的 Django 版本或一個提示你 “No module named django” 的錯誤。此外,還應該檢查下你的版本與本教程的版本是否一致。 若不一致,你可以參考 Django 版本對應的教程或者更新 Django 到最新版本。

請參考 如何安裝 Django 中的意見先刪除舊版本的 Django 再安裝一個新的。

在哪里可以獲得幫助:

如果您在學習本教程中遇到問題,請在 django-users 上發(fā)貼或者在 #django on irc.freenode.net 上與其他可能會幫助您的 Django 用戶交流。

創(chuàng)建一個項目

如果這是你第一次使用 Django ,那么你必須進行一些初始設(shè)置。也就是通過自動生成代碼來建立一個 Django 項目 project – 一個 Django 項目的設(shè)置集,包含了數(shù)據(jù)庫配置、 Django 詳細選項設(shè)置和應用特性配置。

在命令行中,使用 cd 命令進入你想存儲代碼所在的目錄,然后運行以下命令:

django-admin.py startproject mysite

這將在當前目錄創(chuàng)建一個 mysite 目錄。如果失敗了,請查看 Problems running django-admin.py.

Note

你需要避免使用 python 保留字或 Django 組件名作為項目的名稱。尤其是你應該避免使用的命名如: django (與 Django 本身會沖突) 或者 test (與 Python 內(nèi)置的包名會沖突).

這段代碼應該放在哪里?

如果你有一般 PHP 的編程背景(未使用流行的框架),可能會將你的代碼放在 Web 服務(wù)器的文檔根目錄下(例如:/var/www)。而在 Django 中,你不必這么做。將任何 Python 代碼放在你的 Web 服務(wù)器文檔根目錄不會是一個好主意,因為這可能會增加人們通過 Web 方式查看到你的代碼的風險。這不利于安全。

將你的代碼放在你的文檔根目錄 以外 的某些目錄, 例如 /home/mycode 。

讓我們來看看 startproject 都創(chuàng)建了些什么:

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

和你看到的不一樣?

默認的項目布局最近剛剛改變過。如果你看到的是一個“扁平”結(jié)構(gòu)的目錄布局(沒有內(nèi)層 mysite/ 目錄),你很可能正在使用一個和本教程版本不一致的 Django 版本。你需要切換到對應的舊版教程或者使用較新的 Django 版本。

這些文件是:

  • 外層 mysite/ 目錄只是你項目的一個容器。對于 Django 來說該目錄名并不重要; 你可以重命名為你喜歡的。
  • manage.py: 一個實用的命令行工具,可讓你以各種方式與該 Django 項目進行交互。 你可以在 django-admin.py and manage.py 中查看關(guān)于 manage.py 所有的細節(jié)。
  • 內(nèi)層 mysite/ 目錄是你項目中的實際 Python 包。該目錄名就是 Python 包名,通過它你可以導入它里面的任何東西。 (e.g. import mysite.settings).
  • mysite/init.py: 一個空文件,告訴 Python 該目錄是一個 Python 包。(如果你是 Python 新手,請查看官方文檔了解 關(guān)于包的更多內(nèi)容 。)
  • mysite/settings.py: 該 Django 項目的設(shè)置/配置。請查看 Django settings 將會告訴你如何設(shè)置。
  • mysite/urls.py: 該 Django 項目的 URL 聲明; 一份由 Django 驅(qū)動的網(wǎng)站“目錄”。請查看 URL dispatcher 可以獲取更多有關(guān) URL 的信息。
  • mysite/wsgi.py: 一個 WSGI 兼容的 Web 服務(wù)器的入口,以便運行你的項目。請查看 How to deploy with WSGI 獲取更多細節(jié)。

開發(fā)用服務(wù)器

讓我們來驗證是否工作。從外層 mysite 目錄切換進去,若準備好了就運行命令 python manage.py runserver。你將會看到命令行輸出如下內(nèi)容:

Performing system checks...

0 errors found
May 13, 2015 - 15:50:53
Django version 1.8, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

你已經(jīng)啟動了 Django 開發(fā)服務(wù)器,一個純粹的由 Python 編寫的輕量級 Web 服務(wù)器。我們在 Django 內(nèi)包含了這個服務(wù)器,這樣你就可以迅速開發(fā)了,在產(chǎn)品投入使用之前不必去配置一臺生產(chǎn)環(huán)境下的服務(wù)器 – 例如 Apache 。

現(xiàn)在是一個很好的提示時機:不要 在任何類似生產(chǎn)環(huán)境中使用此服務(wù)器。它僅適用于開發(fā)環(huán)境。(我們提供的是 Web 框架的業(yè)務(wù),而不是 Web 服務(wù)器。)

現(xiàn)在服務(wù)器正在運行中,請在你的 Web 瀏覽器中訪問 http://127.0.0.1:8000/ 。 你會看到一個令人愉悅的,柔和的淡藍色 “Welcome to Django” 頁面。它工作正常!

更改端口號

默認情況下,runserver 命令啟動的開發(fā)服務(wù)器只監(jiān)聽本地 IP 的 8000 端口。

如果你想改變服務(wù)器的端口,把它作為一個命令行參數(shù)傳遞即可。例如以下命令啟動的服務(wù)器將監(jiān)聽 8080 端口:

python manage.py runserver 8080

如果你想改變服務(wù)器 IP ,把它和端口號一起傳遞即可。因此,要監(jiān)聽所有公共 IP 地址(如果你想在其他電腦上炫耀你的工作),請使用:

python manage.py runserver 0.0.0.0:8000

有關(guān)開發(fā)服務(wù)器的完整文檔可以在 runserver 內(nèi)參考。

數(shù)據(jù)庫設(shè)置

現(xiàn)在,編輯 mysite/settings.py 。 這是一個普通的 Python 模塊,包含了代表 Django 設(shè)置的模塊級變量。 更改 DATABASES 中 'default' 下的以下鍵的值,以匹配您的數(shù)據(jù)庫連接設(shè)置。

  • ENGINE – 從 'django.db.backends.postgresql_psycopg2', 'django.db.backends.mysql', 'django.db.backends.sqlite3', 'django.db.backends.oracle' 中選一個, 至于其他請查看 also available.
  • NAME – 你的數(shù)據(jù)庫名。如果你使用 SQLite,該數(shù)據(jù)庫將是你計算機上的一個文件;在這種情況下,NAME 將是一個完整的絕對路徑,而且還包含該文件的名稱。如果該文件不存在,它會在第一次同步數(shù)據(jù)庫時自動創(chuàng)建(見下文)。

當指定路徑時,總是使用正斜杠,即使是在 Windows 下(例如:C:/homes/user/mysite/sqlite3.db) 。

  • USER – 你的數(shù)據(jù)庫用戶名 ( SQLite 下不需要) 。
  • PASSWORD – 你的數(shù)據(jù)庫密碼 ( SQLite 下不需要) 。
  • HOST – 你的數(shù)據(jù)庫主機地址。如果和你的數(shù)據(jù)庫服務(wù)器是同一臺物理機器,請將此處保留為空 (或者設(shè)置為 127.0.0.1) ( SQLite 下不需要) 。查看 HOST 了解詳細信息。

如果你是新建數(shù)據(jù)庫,我們建議只使用 SQLite ,將 ENGINE 改為 'django.db.backends.sqlite3' 并且將 NAME 設(shè)置為你想存放數(shù)據(jù)庫的地方。 SQLite 是內(nèi)置在 Python 中的,因此你不需要安裝任何東西來支持你的數(shù)據(jù)庫。

Note

如果你使用 PostgreSQL 或者 MySQL,確保你已經(jīng)創(chuàng)建了一個數(shù)據(jù)庫。還是通過你的數(shù)據(jù)庫交互接口中的 “CREATE DATABASE database_name;” 命令做到這一點的。 如果你使用 SQLite ,你不需要事先創(chuàng)建任何東西 - 在需要的時候,將會自動創(chuàng)建數(shù)據(jù)庫文件。 當你編輯 settings.py 時,將 TIME_ZONE 修改為你所在的時區(qū)。默認值是美國中央時區(qū)(芝加哥)。

同時,注意文件底部的 INSTALLED_APPS 設(shè)置。它保存了當前 Django 實例已激活的所有 Django 應用。每個應用可以被多個項目使用,而且你可以打包和分發(fā)給其他人在他們的項目中使用。

默認情況下,INSTALLED_APPS 包含以下應用,這些都是由 Django 提供的:

  • django.contrib.auth – 身份驗證系統(tǒng)。
  • django.contrib.contenttypes – 內(nèi)容類型框架。
  • django.contrib.sessions – session 框架。
  • django.contrib.sites – 網(wǎng)站管理框架。
  • django.contrib.messages – 消息框架。
  • django.contrib.staticfiles – 靜態(tài)文件管理框架。

這些應用在一般情況下是默認包含的。

所有這些應用中每個應用至少使用一個數(shù)據(jù)庫表,所以在使用它們之前我們需要創(chuàng)建數(shù)據(jù)庫中的表。要做到這一點,請運行以下命令:

python manage.py syncdb

syncdb 命令參照 INSTALLED_APPS 設(shè)置,并在你的 settings.py 文件所配置的數(shù)據(jù)庫中創(chuàng)建必要的數(shù)據(jù)庫表。每創(chuàng)建一個數(shù)據(jù)庫表你都會看到一條消息,接著你會看到一個提示詢問你是否想要在身份驗證系統(tǒng)內(nèi)創(chuàng)建個超級用戶。按提示輸入后結(jié)束。

如果你感興趣,可以在你的數(shù)據(jù)庫命令行下輸入:dt (PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 來列出 Django 所創(chuàng)建的表。

極簡主義者

就像我們上面所說的,一般情況下以上應用都默認包含在內(nèi),但不是每個人都需要它們。如果不需要某些或全部應用,在運行 syncdb 命令前可從 INSTALLED_APPS 內(nèi)隨意注釋或刪除相應的行。syncdb 命令只會為 INSTALLED_APPS 內(nèi)的應用創(chuàng)建表。

創(chuàng)建模型

現(xiàn)在你的項目開發(fā)環(huán)境建立好了, 你可以開工了。

你通過 Djaong 編寫的每個應用都是由 Python 包組成的,這些包存放在你的 Python path 中并且遵循一定的命名規(guī)范。 Django 提供了個實用工具可以自動生成一個應用的基本目錄架構(gòu),因此你可以專注于編寫代碼而不是去創(chuàng)建目錄。

項目 ( Projects ) vs. 應用 ( apps )

項目與應用之間有什么不同之處?應用是一個提供功能的 Web 應用 – 例如:一個博客系統(tǒng)、一個公共記錄的數(shù)據(jù)庫或者一個簡單的投票系統(tǒng)。 項目是針對一個特定的 Web 網(wǎng)站相關(guān)的配置和其應用的組合。一個項目可以包含多個應用。一個應用可以在多個項目中使用。

你的應用可以存放在 Python path 中的任何位置。在本教材中,我們將通過你的 manage.py 文件創(chuàng)建我們的投票應用,以便它可以作為頂層模塊導入,而不是作為 mysite 的子模塊。

要創(chuàng)建你的應用,請確認與 manage.py 文件在同一的目錄下并輸入以下命令:

python manage.py startapp polls

這將創(chuàng)建一個 polls 目錄,其展開的樣子如下所示::

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

此目錄結(jié)構(gòu)就是投票應用。

在 Django 中編寫一個有數(shù)據(jù)庫支持的 Web 應用的第一步就是定義你的模型 – 從本質(zhì)上講就是數(shù)據(jù)庫設(shè)計及其附加的元數(shù)據(jù)。

哲理

模型是有關(guān)你數(shù)據(jù)的唯一且明確的數(shù)據(jù)源。它包含了你所要存儲的數(shù)據(jù)的基本字段和行為。 Django 遵循 DRY 原則 。目標是為了只在一個地方定義你的數(shù)據(jù)模型就可從中自動獲取數(shù)據(jù)。

在這簡單的投票應用中,我們將創(chuàng)建兩個模型: Poll 和 Choice。Poll 有問題和發(fā)布日期兩個字段。Choice 有兩個字段: 選項 ( choice ) 的文本內(nèi)容和投票數(shù)。每一個 Choice 都與一個 Poll 關(guān)聯(lián)。

這些概念都由簡單的 Python 類來表現(xiàn)。編輯 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_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

代碼很簡單。每個模型都由繼承自 django.db.models.Model 子類的類來描述。 每個模型都有一些類變量,每一個類變量都代表了一個數(shù)據(jù)庫字段。

每個字段由一個 Field 的實例來表現(xiàn) – 比如 CharField 表示字符類型的字段和 DateTimeField 表示日期時間型的字段。這會告訴 Django 每個字段都保存了什么類型的數(shù)據(jù)。

每一個 Field 實例的名字就是字段的名字(如: question 或者 pub_date ),其格式屬于親和機器式的。在你的 Python 的代碼中會使用這個值,而你的數(shù)據(jù)庫會將這個值作為表的列名。

你可以在初始化 Field 實例時使用第一個位置的可選參數(shù)來指定人類可讀的名字。這在Django的內(nèi)省部分中被使用到了,而且兼作文檔的一部分來增強代碼的可讀性。若字段未提供該參數(shù),Django 將使用符合機器習慣的名字。在本例中,我們僅定義了一個符合人類習慣的字段名 Poll.pub_date 。對于模型中的其他字段,機器名稱就已經(jīng)足夠替代人類名稱了。

一些 Field 實例是需要參數(shù)的。 例如 CharField 需要你指定 ~django.db.models.CharField.max_length。這不僅適用于數(shù)據(jù)庫結(jié)構(gòu),以后我們還會看到也用于數(shù)據(jù)驗證中。

一個 Field 實例可以有不同的可選參數(shù); 在本例中,我們將 votes 的 default 的值設(shè)為 0 。

最后,注意我們使用了 ForeignKey 定義了一個關(guān)聯(lián)。它告訴 Django 每一個Choice 關(guān)聯(lián)一個 Poll 。 Django 支持常見數(shù)據(jù)庫的所有關(guān)聯(lián):多對一( many-to-ones ),多對多( many-to-manys ) 和 一對一 ( one-to-ones )。

激活模型

剛才那點模型代碼提供給 Django 大量信息。有了這些 Django 就可以做:

為該應用創(chuàng)建對應的數(shù)據(jù)庫架構(gòu) (CREATE TABLE statements) 。 為 Poll 和 Choice 對象創(chuàng)建 Python 訪問數(shù)據(jù)庫的 API 。 但首先,我們需要告訴我們的項目已經(jīng)安裝了 polls 應用。

哲理

Django 應用是“可插拔的”:你可以在多個項目使用一個應用,你還可以分發(fā)應用,因為它們沒有被捆綁到一個給定的 Django 安裝環(huán)境中。

再次編輯 settings.py 文件,在 INSTALLED_APPS 設(shè)置中加入 'polls' 字符。因此結(jié)果如下所示:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'polls',
)

現(xiàn)在 Django 已經(jīng)知道包含了 polls 應用。讓我們運行如下命令:

python manage.py sql polls

你將看到類似如下所示內(nèi)容 ( 有關(guān)投票應用的 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") DEFERRABLE INITIALLY DEFERRED,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
COMMIT;

請注意如下事項:

  • 確切的輸出內(nèi)容將取決于您使用的數(shù)據(jù)庫會有所不同。
  • 表名是自動生成的,通過組合應用名 (polls) 和小寫的模型名 – poll 和 choice 。 ( 你可以重寫此行為。)
  • 主鍵 (IDs) 是自動添加的。( 你也可以重寫此行為。)
  • 按照慣例,Django 會在外鍵字段名上附加 "_id" 。 ( 是的,你仍然可以重寫此行為。)
  • 外鍵關(guān)系由 REFERENCES 語句顯示聲明。
  • 生成 SQL 語句時針對你所使用的數(shù)據(jù)庫,會為你自動處理特定于數(shù)據(jù)庫的字段,例如 auto_increment (MySQL), serial (PostgreSQL), 或 or integer primary key (SQLite) 。 在引用字段名時也是如此 – 比如使用雙引號或單引號。 本教材的作者所使用的是 PostgreSQL,因此例子中輸出的是 PostgreSQL 的語法。
  • 這些 sql 命令其實并沒有在你的數(shù)據(jù)庫中運行過 - 它只是在屏幕上顯示出來,以便讓你了解 Django 認為什么樣的 SQL 是必須的。 如果你愿意,可以把 SQL 復制并粘帖到你的數(shù)據(jù)庫命令行下去執(zhí)行。 但是,我們很快就能看到, Django 提供了一個更簡單的方法來執(zhí)行此 SQL 。

如果你感興趣,還可以運行以下命令:

  • python manage.py validate – 檢查在構(gòu)建你的模型時是否有錯誤。
  • python manage.py sqlcustom polls – 輸出為應用定義的任何 custom SQL statements ( 例如表或約束的修改 ) 。
  • python manage.py sqlclear polls – 根據(jù)存在于你的數(shù)據(jù)庫中的表 (如果有的話) ,為應用輸出必要的 DROP TABLE 。
  • python manage.py sqlindexes polls – 為應用輸出 CREATE INDEX 語句。
  • python manage.py sqlall polls – 輸出所有 SQL 語句:sql, sqlcustom, 和 sqlindexes 。

看看這些輸出的命令可以幫助你理解框架底層實際上處理了些什么。

現(xiàn)在,再次運行 syncdb 命令在你的數(shù)據(jù)庫中創(chuàng)建這些模型對應的表:

python manage.py syncdb

syncdb 命令會給在 INSTALLED_APPS 中有但數(shù)據(jù)庫中沒有對應表的應用執(zhí)行 sqlall 操作。 該操作會為你上一次執(zhí)行 syncdb 命令以來在項目中添加的任何應用創(chuàng)建對應的表、初始化數(shù)據(jù)和創(chuàng)建索引。 syncdb 命令只要你喜歡就可以任意調(diào)用,并且它僅會創(chuàng)建不存在的表。

請閱讀 django-admin.py documentation 文檔了解 manage.py 工具更多的功能。

玩轉(zhuǎn) API

現(xiàn)在,我們進入 Python 的交互式 shell 中玩弄 Django 提供給你的 API 。要調(diào)用 Python sell ,使用如下命令:

python manage.py shell

我們當前使用的環(huán)境不同于簡單的輸入 “python” 進入的 shell 環(huán)境,因為 manage.py 設(shè)置了 DJANGO_SETTINGS_MODULE 環(huán)境變量,該變量給定了 Django 需要導入的 settings.py 文件所在路徑。

忽略 manage.py

若你不想使用 manage.py ,也是沒有問題的。 僅需要將 DJANGO_SETTINGS_MODULE 環(huán)境變量值設(shè)為 mysite.settings 并在與 manage.py 文件所在同一目錄下運行 python ( 或確保目錄在 Python path 下,那 import mysite 就可以了 )。

想了解更多的信息,請參考 django-admin.py 文檔 。

一旦你進入了 shell,就可通過 database API 來瀏覽數(shù)據(jù)::

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

#  系統(tǒng)中還沒有 polls 。
>>> Poll.objects.all()
[]

# 創(chuàng)建一個新 Poll 。
# 在默認配置文件中時區(qū)支持配置是啟用的,
# 因此 Django 希望為 pub_date 字段獲取一個 datetime  with tzinfo 。使用了 timezone.now()
# 而不是 datetime.datetime.now() 以便獲取正確的值。
>>> from django.utils import timezone
>>> p = Poll(question="What's new?", pub_date=timezone.now())

# 保存對象到數(shù)據(jù)庫中。你必須顯示調(diào)用 save() 方法。
>>> p.save()

# 現(xiàn)在對象擁有了一個ID 。請注意這可能會顯示 "1L" 而不是 "1",取決于
# 你正在使用的數(shù)據(jù)庫。 這沒什么大不了的,它只是意味著你的數(shù)據(jù)庫后端
# 喜歡返回的整型數(shù)作為 Python 的長整型對象而已。
>>> p.id
1

# 通過 Python 屬性訪問數(shù)據(jù)庫中的列。
>>> p.question
"What's new?"
>>> p.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# 通過改為屬性值來改變值,然后調(diào)用 save() 方法。
>>> p.question = "What's up?"
>>> p.save()

# objects.all() 用以顯示數(shù)據(jù)庫中所有的 polls 。
>>> Poll.objects.all()
[<Poll: Poll object>]

請稍等。<Poll: Poll object> 這樣顯示對象絕對是無意義的。 讓我們編輯 polls 模型( 在 polls/models.py 文件中 ) 并且給 Poll 和 Choice 都添加一個 unicode() 方法來修正此錯誤:

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

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

給你的模型添加 unicode() 方法是很重要的, 不僅是讓你在命令行下有明確提示,而且在 Django 自動生成的管理界面中也會使用到對象的呈現(xiàn)。

為什么是 unicode() 而不是 str()?

如果你熟悉 Python,那么你可能會習慣在類中添加 str() 方法而不是 unicode() 方法。 We use 我們在這里使用 unicode() 是因為 Django 模型默認處理的是 Unicode 格式。當所有存儲在數(shù)據(jù)庫中的數(shù)據(jù)返回時都會轉(zhuǎn)換為 Unicode 的格式。

Django 模型有個默認的 str() 方法 會去調(diào)用 unicode() 并將結(jié)果轉(zhuǎn)換為 UTF-8 編碼的字符串。這就意味著 unicode(p) 會返回一個 Unicode 字符串,而 str(p) 會返回一個以 UTF-8 編碼的普通字符串。

如果這讓你感覺困惑,那么你只要記住在模型中添加 unicode() 方法。 運氣好的話,這些代碼會正常運行。

請注意這些都是普通的 Python 方法。讓我們來添加個自定義方法,為了演示而已:

import datetime
from django.utils import timezone
# ...
class Poll(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

請注意,增加了 import datetime 和 from django.utils import timezone, 是為了分別引用 Python 的標準庫 datetime 模塊和 Django 的 django.utils.timezone 中的 time-zone-related 實用工具 。如果你不熟悉在 Python 中處理時區(qū),你可以在 時區(qū)支持文檔 學到更多。

保存這些更改并且再次運行 python manage.py shell 以開啟一個新的 Python shell:

>>> from polls.models import Poll, Choice

# 確認我們附加的  __unicode__() 正常運行。
>>> Poll.objects.all()
[<Poll: What's up?>]

# Django 提供了一個豐富的數(shù)據(jù)庫查詢 API ,
# 完全由關(guān)鍵字參數(shù)來驅(qū)動。
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]

# 獲取今年發(fā)起的投票。
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Poll.objects.get(pub_date__year=current_year)
<Poll: What's up?>

# 請求一個不存在的 ID ,這將引發(fā)一個異常。
>>> Poll.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Poll matching query does not exist. Lookup parameters were {'id': 2}

# 根據(jù)主鍵查詢是常見的情況,因此 Django 提供了一個
# 主鍵精確查找的快捷方式。
# 以下代碼等同于 Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: What's up?>

# 確認我們自定義方法正常運行。
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True

# 給 Poll 設(shè)置一些 Choices 。通過 create 方法調(diào)用構(gòu)造方法去創(chuàng)建一個新
# Choice 對象實例,執(zhí)行 INSERT 語句后添加該 choice 到
# 可用的 choices 集中并返回這個新建的 Choice 對象實例。 Django 創(chuàng)建了
# 一個保存外鍵關(guān)聯(lián)關(guān)系的集合 ( 例如 poll 的 choices) 以便可以通過 API
# 去訪問。
>>> p = Poll.objects.get(pk=1)

# 從關(guān)聯(lián)對象集中顯示所有 choices  -- 到目前為止還沒有。
>>> p.choice_set.all()
[]

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

# Choice 對象擁有訪問它們關(guān)聯(lián)的 Poll 對象的 API 。
>>> 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 會自動連續(xù)關(guān)聯(lián)。
# 使用雙下劃線來隔離關(guān)聯(lián)。
# 只要你想要幾層關(guān)聯(lián)就可以有幾層關(guān)聯(lián),沒有限制。
# 尋找和今年發(fā)起的任何 poll 有關(guān)的所有 Choices
# ( 重用我們在上面建立的 'current_year' 變量 )。
>>> Choice.objects.filter(poll__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# 讓我們使用 delete() 刪除 choices 中的一個。
>>> c = p.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

欲了解更多有關(guān)模型關(guān)系的信息,請查看 訪問關(guān)聯(lián)對象 。欲了解更多有關(guān)如何使用雙下劃線來通過 API 執(zhí)行字段查詢的,請查看 字段查詢 。 如需完整的數(shù)據(jù)庫 API 信息,請查看我們的 數(shù)據(jù)庫 API 參考 。

當你對 API 有所了解后, 請查看 教程 第2部分 來學習 Django 的自動生成的管理網(wǎng)站是如何工作的。

譯者:Django 文檔協(xié)作翻譯小組,原文:Part 1: Models

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。