上一節(jié): Django 官網(wǎng)最新 Tutorial 渣翻 - Part 1
手寫(xiě)第一個(gè)Django應(yīng)用, 第二部分
我們本節(jié)開(kāi)始配置數(shù)據(jù)庫(kù),創(chuàng)建你的第一個(gè)model,并且快速了解下Django的自動(dòng)生成的 admin (后臺(tái)管理)頁(yè)面.
數(shù)據(jù)庫(kù)配置
打開(kāi) mysite/settings.py, 這是一個(gè)普通的python模塊, 包含了Django配置的模塊級(jí)變量。
默認(rèn)情況下, Django 用的時(shí) SQLite, 如果你是數(shù)據(jù)庫(kù)新手, 或者僅僅想試一下Django. 這是最簡(jiǎn)單的選擇, python 自帶了SQLite模塊, 所以無(wú)需再裝其他東西, 當(dāng)你真正想寫(xiě)一個(gè)項(xiàng)目時(shí),你可能需要用到功能更豐富的數(shù)據(jù)庫(kù),比如說(shuō)PostgreSQL,避免后面面臨數(shù)據(jù)庫(kù)切換的頭疼問(wèn)題.
如果你想用其他的數(shù)據(jù)庫(kù),請(qǐng)先安裝好相應(yīng)的數(shù)據(jù)庫(kù)軟件 ,并修改settings文件中DATABASES中 'default' 鍵的值,用于連接你的數(shù)據(jù)庫(kù):
- ENGINE
可以是’django.db.backends.sqlite3’或者’django.db.backends.postgresql’,’django.db.backends.mysql’, or ’django.db.backends.oracle’,當(dāng)然 其它可用的也行. - NAME
數(shù)據(jù)庫(kù)的名字。如果你使用的是默認(rèn)的SQLite,那么數(shù)據(jù)庫(kù)將作為一個(gè)文件將存放在你的本地機(jī)器內(nèi),NAME應(yīng)該是這個(gè)文件的完整絕對(duì)路徑,包括文件名。設(shè)置中的默認(rèn)值os.path.join(BASE_DIR, ’db.sqlite3’),將把該文件儲(chǔ)存在你的項(xiàng)目目錄下。
如果你不是用SQLite,那你需要配置其他的設(shè)置,如 USER, PASSWORD, and HOST 都是必需的. 詳細(xì)請(qǐng)看 DATABASES相關(guān).
SQLite外的其他數(shù)據(jù)庫(kù):
在使用非SQLite的數(shù)據(jù)庫(kù)時(shí),請(qǐng)務(wù)必首先在數(shù)據(jù)庫(kù)提示符交互模式下創(chuàng)建數(shù)據(jù)庫(kù),你可以使用命令:“CREATE DATABASE database_name;” 確保你在settings文件中提供的數(shù)據(jù)庫(kù)用戶(hù)具有創(chuàng)建數(shù)據(jù)庫(kù)表的權(quán)限,因?yàn)樵诮酉聛?lái)的教程中,我們需要自動(dòng)創(chuàng)建一個(gè)test數(shù)據(jù)庫(kù)。 如果你使用的是SQLite,那么你無(wú)需做任何預(yù)先配置,數(shù)據(jù)庫(kù)文件會(huì)自動(dòng)創(chuàng)建
在修改settings文件時(shí),請(qǐng)順便將TIME_ZONE設(shè)置為你所在的時(shí)區(qū)。(天朝: TIME_ZONE = 'UTC')
同時(shí),請(qǐng)注意settings文件中頂部的INSTALLED_APPS設(shè)置項(xiàng)。它保存了所有的在當(dāng)前項(xiàng)目中被激活的Django應(yīng)用。你必須將你自定義的app注冊(cè)在這里。每個(gè)應(yīng)用可以被多個(gè)項(xiàng)目使用,而且你可以打包和分發(fā)給其他人在他們的項(xiàng)目中使用。
默認(rèn)情況,INSTALLED_APPS 中包含以下應(yīng)用,它們都是Django自帶的:
-
django.contrib.admin– admin站點(diǎn), 你很快會(huì)用到. -
django.contrib.auth– 身份認(rèn)證系統(tǒng). -
django.contrib.contenttypes– 內(nèi)容類(lèi)型框架. -
django.contrib.sessions– sessions 框架. -
django.contrib.messages– 消息框架. -
django.contrib.staticfiles– 靜態(tài)文件管理框架.
以上應(yīng)用默認(rèn)會(huì)包含,對(duì)于大多數(shù)項(xiàng)目都是需要的.
上面的每個(gè)應(yīng)用都至少需要使用一個(gè)數(shù)據(jù)庫(kù)表,所以在使用它們之前我們需要在數(shù)據(jù)庫(kù)中創(chuàng)建這些表。使用這個(gè)命令:
python manage.py migrate
migrate命令將根據(jù)INSTALLED_APPS、mysite/settings.py的數(shù)據(jù)庫(kù)設(shè)置以及app的數(shù)據(jù)庫(kù)遷移(稍后會(huì)講到)信息創(chuàng)建相關(guān)的表 ,你將看到每一個(gè)數(shù)據(jù)庫(kù)消息的信息。如果你感興趣,可以在你的數(shù)據(jù)庫(kù)命令行下輸入:\dt (PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite), 或SELECT TABLE_NAME FROM USER_TABLES; (Oracle) 來(lái)列出 Django 所創(chuàng)建的表。
關(guān)于簡(jiǎn)化
就像我們上面說(shuō)的,默認(rèn)情況下會(huì)自帶那些公共應(yīng)用,但不是每一個(gè)應(yīng)用都需要這么多。如果你不需要其中一個(gè)或所有的,你可以在migrate前,將INSTALLED_APPS內(nèi)注釋掉或者刪除對(duì)應(yīng)的行。 migrate命令只會(huì)針對(duì)INSTALL_APPS進(jìn)行數(shù)據(jù)庫(kù)遷移.
創(chuàng)建Model
現(xiàn)在我們開(kāi)始定義models - 本質(zhì)上,就是你的數(shù)據(jù)庫(kù)結(jié)構(gòu),和其他的一些元數(shù)據(jù)信息.
哲(♂)學(xué)
model就是你唯一明確的真實(shí)數(shù)據(jù)源。Django 遵循 DRY Principle.目的是讓你可以在一個(gè)地方定義你的數(shù)據(jù)模型, 從中生成數(shù)據(jù).
在我們的投票應(yīng)用中,我們將創(chuàng)建兩個(gè)模型:Question and Choice。Question表包含問(wèn)題和發(fā)布日期兩個(gè)字段。Choice表有兩個(gè)字段:選擇文本和投票計(jì)數(shù)。每一條choice都關(guān)聯(lián)到一條Question。
這些概念都由python的類(lèi)來(lái)定義。編輯polls/models.py,如下:
polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
以上代碼簡(jiǎn)單明了。每一個(gè)model都由一個(gè)類(lèi)來(lái)定義,該類(lèi)是django.db.models.Model的子類(lèi)。每個(gè)類(lèi)都由數(shù)個(gè)變量組成,分別對(duì)應(yīng)了數(shù)據(jù)庫(kù)里的字段。
每一個(gè)字段都是Field 類(lèi)的實(shí)例 -- 如 CharField是字符串字段,DateTimeField是時(shí)間字段。這告訴Django每個(gè)字段用來(lái)存儲(chǔ)什么類(lèi)型的數(shù)據(jù)。
每個(gè)Field的實(shí)例名(如question_text 或 pub_date)就是字段的名字名,一個(gè)機(jī)器友好型的名字。在代碼里你會(huì)用到它,而數(shù)據(jù)庫(kù)里用它來(lái)作字段名。
每個(gè)Filed里的第一個(gè)可選的位置參數(shù),常常被用來(lái)指定一個(gè)可讀性好的名字。這在Django的一些內(nèi)部機(jī)制中有所用處,也可以兼做文檔。如果沒(méi)有指定這個(gè)字段,Django會(huì)默認(rèn)使用機(jī)器可讀的名字。在這個(gè)例子中,我們只為pub_data定義了友好的名字。model的其他字段已經(jīng)通俗易懂。
有一些字段有必選參數(shù)。例如,CharField要求你給它一個(gè)max_length。這個(gè)參數(shù)不僅在建表時(shí)用到,在數(shù)據(jù)驗(yàn)證中也會(huì)用到,我們稍后會(huì)看到。
Field 還具有各種可選位置參數(shù)。在這個(gè)例子中,我們?cè)O(shè)置votes字段的default參數(shù)為0。
最后,注意我們使用ForeignKey定義了一個(gè)外鍵關(guān)聯(lián)。它告訴Django每個(gè)Choice都只關(guān)聯(lián)一個(gè)Question。Django支持所有常見(jiàn)的數(shù)據(jù)庫(kù)關(guān)聯(lián):多對(duì)一、多對(duì)多和一對(duì)一。
激活 model
這簡(jiǎn)短的model代碼給了Django許多信息。有了它,Django就可以:
- 為該應(yīng)用創(chuàng)建數(shù)據(jù)庫(kù)表(CREATE TABLE 語(yǔ)句)。
- 創(chuàng)建一個(gè)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的 python API 來(lái)訪(fǎng)問(wèn)Question對(duì)象和Choice對(duì)象。
但是,我們首先得告訴項(xiàng)目:polls應(yīng)用已經(jīng)安裝。
哲學(xué)
Django 應(yīng)用是“插件化”的,即可以在多個(gè)項(xiàng)目中使用同一個(gè)應(yīng)用,也可以分發(fā)這些應(yīng)用, 因?yàn)樗鼈儾恍枰c某個(gè)特定的Django安裝綁定。
為了將App整合進(jìn)項(xiàng)目里,我們需要在 settings.py 的 INSTALLED_APPS 里添加該 App 的引用,PollsConfig 類(lèi)在 polls/apps.py 文件中,所以按照點(diǎn)來(lái)分割路徑就是polls.apps.PollsConfig,編輯mysite/settings.py文件,在 INSTALLED_APPS中添加按點(diǎn)分割的路徑,如下:
mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
現(xiàn)在Django就知道他整合了polls應(yīng)用。我們輸入以下命令:
python manage.py makemigrations polls
你可以看到類(lèi)似以下的輸出:
Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
通過(guò)運(yùn)行makemigrations,你將告訴Django你已經(jīng)對(duì)你的models做了一些修改(在本例中,你創(chuàng)建了新的model類(lèi)),這些修改會(huì)作為migration記錄來(lái)存儲(chǔ)。
Migrations 就是Django存儲(chǔ)的models修改記錄(也就是數(shù)據(jù)庫(kù)表) - 他們只是在磁盤(pán)的文件, 你可以查看剛剛創(chuàng)建新model時(shí)產(chǎn)生的migration, 他們?cè)?code>polls/migrations/0001_initial.py文件里, 別擔(dān)心, 你無(wú)需每次都去看一下, 但是他們是可編輯的, 以便有時(shí)候你想修改他們.
There’s a command that will run the migrations for you and manage your database schema automatically - that’s called migrate, and we’ll come to it in a moment - but first, let’s see what SQL that migration would run. The sqlmigrate command takes migration names and returns their SQL:
有一個(gè)命令可以運(yùn)行這些migrations文件來(lái)自動(dòng)管理你的數(shù)據(jù)庫(kù)表, -- 它就是migrate, 我們待會(huì)兒會(huì)用到它 -- 但首先我們看一下,那些migration會(huì)執(zhí)行哪些sql語(yǔ)句。sqlmigrate 命令接收migration文件名,并返回sql語(yǔ)句:
python manage.py sqlmigrate polls 0001
你將看到類(lèi)似以下輸出(我們重新排版了下)
BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
COMMIT;
請(qǐng)注意以下幾點(diǎn):
- 輸出的具體內(nèi)容會(huì)依據(jù)你使用的數(shù)據(jù)庫(kù)而不同。 以上例子使用的數(shù)據(jù)庫(kù)是PostgreSQL。
- 表名是自動(dòng)生成的,由app的名字(polls)和模型名字的小寫(xiě)字母組合而成 —— question和choice。(你可以重寫(xiě)這個(gè)行為。)
- 主鍵(IDs)是自動(dòng)添加的。 (你也可以重寫(xiě)這個(gè)行為。)
- 按照慣例,Django會(huì)在外鍵的字段名后面添加 "_id"。(是的,你依然可以重寫(xiě)這個(gè)行為。)
- 外鍵關(guān)系由FOREIGN KEY約束顯式聲明。不用在意DEFERRABLE 部分;它只是告訴PostgreSQL直到事務(wù)的最后再執(zhí)行外鍵關(guān)聯(lián)。
- 這些SQL語(yǔ)句是針對(duì)你所使用的數(shù)據(jù)庫(kù)定制的,所以會(huì)為你自動(dòng)處理某些數(shù)據(jù)庫(kù)所特有的字段例如auto_increment(MySQL)、 serial (PostgreSQL)或integer primary key autoincrement (SQLite) 。在處理字段名的引號(hào)時(shí)也是如此 —— 例如,使用雙引號(hào)還是單引號(hào)。
-
sqlmigrate命令并不會(huì)在你的數(shù)據(jù)庫(kù)上真正運(yùn)行遷移文件 —— 它只是把Django 認(rèn)為需要的SQL打印在屏幕上以讓你能夠看到。 這對(duì)于檢查Django將要進(jìn)行的數(shù)據(jù)庫(kù)操作或者你的數(shù)據(jù)庫(kù)管理員需要這些SQL腳本是非常有用的。
如果有興趣,你還可以運(yùn)行python manage.py check, 它會(huì)檢查你的項(xiàng)目中的模型是否存在問(wèn)題,而不用執(zhí)行遷移或者操作數(shù)據(jù)庫(kù)
現(xiàn)在,再次運(yùn)行 migrate, 在你的數(shù)據(jù)庫(kù)中創(chuàng)建model所對(duì)應(yīng)的表:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
migrate 命令將找到所有尚未被應(yīng)用的遷移文件(Django有專(zhuān)門(mén)的一張表 - django_migrations, 來(lái)追蹤哪些遷移文件已經(jīng)被應(yīng)用過(guò)),并且在你的數(shù)據(jù)庫(kù)上運(yùn)行它們 —— 本質(zhì)上來(lái)講,就是同步你對(duì)models的修改到數(shù)據(jù)庫(kù)表中。)
Migrations 功能非常強(qiáng)大,在你開(kāi)發(fā)項(xiàng)目的過(guò)程中,當(dāng)你在更改models后,無(wú)需刪除數(shù)據(jù)庫(kù)或表再重建。它專(zhuān)注于熱升級(jí)你的數(shù)據(jù)庫(kù)且不丟數(shù)據(jù)。我們將在本教程的后續(xù)章節(jié)中詳細(xì)介紹,但是現(xiàn)在,請(qǐng)記住模型變更的三個(gè)基本步驟:
- 修改你的模型(在models.py文件中)。
- 運(yùn)行
python manage.py makemigrations,為這些修改創(chuàng)建遷移文件 - 運(yùn)行
python manage.py migrate,將這些改變更新到數(shù)據(jù)庫(kù)中。
將生成和應(yīng)用Migrations命令分開(kāi), 是因?yàn)槟憧赡苄枰獙⑦w移文件提交到你的版本控制器并跟隨你的應(yīng)用, 這樣做不僅使開(kāi)發(fā)變得更加簡(jiǎn)單,而且對(duì)其他開(kāi)發(fā)者以及線(xiàn)上環(huán)境非常有用。
閱讀 django-admin documentation 來(lái)詳細(xì)了解manage.py 工具所能做的事情。
玩玩API
現(xiàn)在,我們切換到python shell的交互模式,感受一下Django給的API。用如下命令來(lái)調(diào)出python shell:
$ python manage.py shell
我們使用這個(gè)(python manage.py shell)而不是直接進(jìn)入python交互環(huán)境(python), 因?yàn)?code>manage.py設(shè)置了DJANGO_SETTINGS_MODULE環(huán)境變量. 它告訴Django導(dǎo)入了mysite/settings.py模塊.
一旦你進(jìn)入了這個(gè)python shell, 那我們就開(kāi)始探索這些database API吧:
>>> from polls.models import Choice, Question # 導(dǎo)入我們剛剛創(chuàng)建的model類(lèi).
# 目前還沒(méi)有questions對(duì)象
>>> Question.objects.all()
<QuerySet []>
# 創(chuàng)建一個(gè)Questions對(duì)象
# 默認(rèn)的設(shè)置文件中是支持時(shí)區(qū)的,
# 所以Django會(huì)通過(guò) tzinfo 模塊給 pub_date 一個(gè)datetime.
# 使用timezone.now(), 它會(huì)替代datetime.datetime.now()完成時(shí)間設(shè)置工作.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# 調(diào)用 save() 來(lái)將對(duì)象保存進(jìn)數(shù)據(jù)庫(kù)
>>> q.save()
# 現(xiàn)在他有一個(gè)id了
>>> q.id
1
# 通過(guò)訪(fǎng)問(wèn)Python屬性的方式來(lái)訪(fǎng)問(wèn)model字段的值
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# 通過(guò)改變對(duì)象屬性的方式來(lái)改變字段的值, 改變后需要調(diào)用save()才能生效
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() 顯示所有在數(shù)據(jù)庫(kù)中的questions對(duì)象
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
秋德馬嘚, <Question: Question object (1)>是什么鬼? 這可不是一種友好的對(duì)象表示方式, 讓我們編輯Question 模型(在 polls/models.py 文件中)來(lái)完善他, 對(duì)Question and Choice類(lèi)都添加__str__() 方法:
polls/models.py
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
給你的模型類(lèi)添加__str__() 方法很重要,不僅會(huì)使你自己在使用交互式命令行時(shí)看得更加方便,而且會(huì)在Django自動(dòng)生成的管理界面中對(duì)模型對(duì)象使用這種表示。
這是非常普通的Python方法?,F(xiàn)在讓我們來(lái)演示一下如何添加自定義方法:
polls/models.py
import datetime
from django.db import models
from django.utils import timezone
class Question(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 的標(biāo)準(zhǔn)datetime 模塊和 Django的django.utils.timezone中時(shí)區(qū)相關(guān)的工具, 如果你不了解Python中時(shí)區(qū)的處理方法,你可以在time zone support docs中了解更多的知識(shí)。
保存這些改動(dòng),然后通過(guò)python manage.py shell另外打開(kāi)一個(gè)新的Python 交互式shell:
>>> from polls.models import Choice, Question
# 確保我們添加的__str__方法生效了
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django提供大量的數(shù)據(jù)庫(kù)查詢(xún)API, 通過(guò)關(guān)鍵字參數(shù)的方式來(lái)調(diào)用.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# 得到今年發(fā)布的question對(duì)象
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# 當(dāng)請(qǐng)求的ID不存在時(shí), 會(huì)拋出異常
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# 大多數(shù)情況下都是通過(guò)主鍵進(jìn)行查詢(xún), 所以Django提供一個(gè)關(guān)于主鍵查詢(xún)的快捷方式
# 以下與Question.objects.get(id=1)是一樣的.
>>> Question.objects.get(pk=1)
<Question: What's up?>
# 確保我們自定義方法生效
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# 每個(gè)question對(duì)象都有多個(gè)choice對(duì)象(一對(duì)多), 調(diào)用 create 來(lái)構(gòu)造一個(gè)新的 choice 對(duì)象,
# 它會(huì)使用 INSERT 語(yǔ)句, 添加choice對(duì)象的一系列字段, 然后返回一個(gè)choice對(duì)象,
# django通過(guò)API來(lái)創(chuàng)建一個(gè)含有"反向關(guān)聯(lián)"關(guān)系的外鍵集合.首先, 我們要獲取指定的question對(duì)象
>>> q = Question.objects.get(pk=1)
# 顯示所有與choices對(duì)象有關(guān)系的對(duì)象集合 -- 目前沒(méi)有
>>> q.choice_set.all()
<QuerySet []>
# 創(chuàng)建3個(gè)choice對(duì)象
# (譯者注: choice類(lèi)中定義了question的外鍵, 所以question可以通過(guò)`類(lèi)名_set`來(lái)反向關(guān)聯(lián),
# 也可以通過(guò)定義外鍵時(shí)設(shè)置的related_name參數(shù)的值來(lái)進(jìn)行反向關(guān)聯(lián))
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice 對(duì)象有API來(lái)訪(fǎng)問(wèn)他們關(guān)聯(lián)的 Question 對(duì)象
>>> c.question
<Question: What's up?>
# 反之亦然: Question對(duì)象也可以訪(fǎng)問(wèn)Choice對(duì)象.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# 我們可以使用雙下劃線(xiàn)來(lái)調(diào)用API自動(dòng)的處理關(guān)系, 其中關(guān)系的深度沒(méi)有限制.(這段感覺(jué)沒(méi)翻譯好, 原文在)
# 如下, 找到所有 pub_date 為今年, 并且可以是屬于任何Question的Choice(這里重用了我們?cè)谏厦鎰?chuàng)建的`current_year`變量.
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# 我們可以使用delete()來(lái)刪除這些choices QuerySet中的一個(gè).
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
更多關(guān)于模型相關(guān)的信息,請(qǐng)查看 Accessing related objects。更多關(guān)于如何在這些API中使用雙下劃線(xiàn)來(lái)執(zhí)行字段查詢(xún)的信息,請(qǐng)查看 Field lookups.。想了解所有數(shù)據(jù)庫(kù)API的信息,請(qǐng)查看我們的 Database API reference.
介紹 Django Admin
哲♂學(xué)
為你的團(tuán)隊(duì)或客戶(hù)編寫(xiě)增刪改查的admin管理系統(tǒng)是非常乏味的,也沒(méi)有多少創(chuàng)造性?xún)r(jià)值?;谶@考慮,Django自動(dòng)的為你的models創(chuàng)建了管理接口。
Django最初是為新聞?wù)军c(diǎn)開(kāi)發(fā)的,新聞發(fā)布者和公共站點(diǎn)界限明顯。管理員通過(guò)這個(gè)系統(tǒng)添加新聞、時(shí)間、體育賽事等,這些信息展示在公共網(wǎng)站上。Django提供了一個(gè)統(tǒng)一接口給站點(diǎn)管理員來(lái)編輯內(nèi)容。
admin系統(tǒng)并不是為了訪(fǎng)客設(shè)計(jì)的,只對(duì)站點(diǎn)管理員開(kāi)放。
創(chuàng)建管理員
首先我們需要?jiǎng)?chuàng)建一個(gè)能登錄admin站點(diǎn)的用戶(hù),運(yùn)行以下命令:
python manage.py createsuperuser
輸入你喜歡的名字,按下回車(chē):
Username: admin
然后會(huì)提示輸入你的郵箱:
Email address: admin@example.com
最后一步是輸入密碼。你需要輸入兩次,第二次作為第一次的進(jìn)一步確認(rèn):
Password: **********
Password (again): *********
Superuser created successfully.
啟動(dòng)開(kāi)發(fā)服務(wù)器
Django的admin站點(diǎn)默認(rèn)是激活的。讓我們開(kāi)啟開(kāi)發(fā)服務(wù)器來(lái)探索一下:
如果服務(wù)器沒(méi)開(kāi)啟,用下面的方法來(lái)啟動(dòng):
python manage.py runserver
現(xiàn)在,打開(kāi)web瀏覽器,本地域名訪(fǎng)問(wèn)“/admin/” -- 比如說(shuō)http://127.0.0.1:8000/admin/。你可以看到admin的登錄界面:
translation 默認(rèn)是開(kāi)啟的,登錄界面顯示的應(yīng)該是你的母語(yǔ),這取決于你的瀏覽器設(shè)置,如果Django有這種翻譯版本的話(huà)。
進(jìn)入admin頁(yè)面
現(xiàn)在,你可以用你剛剛創(chuàng)建的超級(jí)用戶(hù)來(lái)登錄了。登錄后你應(yīng)該可以看到如下index頁(yè)面:

當(dāng)前已經(jīng)有兩個(gè)可編輯的內(nèi)容:groups和users。它們是
django.contrib.auth模塊提供的身份認(rèn)證框架。
在admin中注冊(cè)投票應(yīng)用
但是我們創(chuàng)建的投票應(yīng)用哪去了呢?它并沒(méi)有在admin的首頁(yè)里。我們還有一件事要做:告訴admin站點(diǎn)Question要有admin交互界面。編輯polls/admin.py文件,代碼如下:
polls/admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
探索Admin功能
Question注冊(cè)之后,Django就知道要將它展示在admin的首頁(yè)了。

點(diǎn)擊“Questions”。 現(xiàn)在,你會(huì)進(jìn)入Question的“變更列表”。 這個(gè)界面顯示了數(shù)據(jù)庫(kù)中的所有question,你可以選擇一個(gè)來(lái)更改它。 我們?cè)谇懊鎰?chuàng)建的“What’s up?” Question對(duì)象也在這里:

點(diǎn)擊“What’s up?” Question對(duì)象來(lái)編輯它:

注意事項(xiàng):
- 這個(gè)表單是根據(jù)
Question模型文件自動(dòng)生成的。 - 模型中不同類(lèi)型的字段(
DateTimeField,CharField)會(huì)對(duì)應(yīng)相應(yīng)的HTML輸入控件。每一種類(lèi)型的字段,Django管理站點(diǎn)都知道如何顯示它們。 - 每個(gè)
DateTimeField字段都會(huì)有個(gè)方便的JavaScript快捷鍵。Date有個(gè)“Today”的快捷鍵和一個(gè)彈出式日歷,time欄有個(gè)“Now”的快捷鍵和一個(gè)列出常用時(shí)間選項(xiàng)的彈出式窗口。
界面的底部提供了幾個(gè)按鈕:
- Save —— 保存更改,并返回當(dāng)前類(lèi)型對(duì)象的變更列表界面。
- Save and continue editing —— 保存更改并且重新載入當(dāng)前對(duì)象的管理界面。
- Save and add another —— 保存更改并且載入一個(gè)當(dāng)前類(lèi)型對(duì)象的新的、空白的表單。
- Delete —— 顯示一個(gè)刪除確認(rèn)界面。
如果“Date published”的值和你在教程1中創(chuàng)建這個(gè)Question對(duì)象時(shí)的時(shí)間不相符,可能是因?yàn)槟阃泴IME_ZONE設(shè)置為你當(dāng)?shù)氐臅r(shí)區(qū)。修改它,然后刷新界面,再次檢查一下是否正確。
通過(guò)“Today”和“Now”這兩個(gè)快捷鍵更改“Date published”字段。,然后點(diǎn)擊 “Save and continue editing”。然后點(diǎn)擊右上角的“History”按鈕。 你將看到一個(gè)頁(yè)面,列出了通過(guò)Django管理界面對(duì)此對(duì)象所做的全部更改的清單,包含有時(shí)間戳和修改人的姓名等信息:

當(dāng)你適應(yīng)了models的API,熟悉了admin站點(diǎn)后,請(qǐng)移步 part 3 of this tutorial 來(lái)學(xué)習(xí)如何給投票應(yīng)用編寫(xiě)更多的views函數(shù).
下一節(jié): Django 官網(wǎng)最新 Tutorial 渣翻 - Part 3