Django做一個(gè)投票應(yīng)用-第二章

數(shù)據(jù)庫配置?

現(xiàn)在胆萧,打開?mysite/settings.py?。這是個(gè)包含了 Django 項(xiàng)目設(shè)置的 Python 模塊。

通常跌穗,這個(gè)配置文件使用 SQLite 作為默認(rèn)數(shù)據(jù)庫订晌。如果你不熟悉數(shù)據(jù)庫,或者只是想嘗試下 Django蚌吸,這是最簡單的選擇锈拨。Python 內(nèi)置 SQLite,所以你無需安裝額外東西來使用它羹唠。當(dāng)你開始一個(gè)真正的項(xiàng)目時(shí)奕枢,你可能更傾向使用一個(gè)更具擴(kuò)展性的數(shù)據(jù)庫,例如 PostgreSQL佩微,避免中途切換數(shù)據(jù)庫這個(gè)令人頭疼的問題缝彬。

如果你想使用其他數(shù)據(jù)庫,你需要安裝合適的?database bindings?哺眯,然后改變?cè)O(shè)置文件中?DATABASES?'default'?項(xiàng)目中的一些鍵值:

ENGINE?-- 可選值有?'django.db.backends.sqlite3'谷浅,'django.db.backends.postgresql','django.db.backends.mysql'奶卓,或?'django.db.backends.oracle'一疯。其它?可用后端

NAME?- 數(shù)據(jù)庫的名稱夺姑。如果使用的是 SQLite墩邀,數(shù)據(jù)庫將是你電腦上的一個(gè)文件,在這種情況下瑟幕,?NAME?應(yīng)該是此文件的絕對(duì)路徑磕蒲,包括文件名。默認(rèn)值?os.path.join(BASE_DIR,?'db.sqlite3')?將會(huì)把數(shù)據(jù)庫文件儲(chǔ)存在項(xiàng)目的根目錄只盹。

如果你不使用 SQLite辣往,則必須添加一些額外設(shè)置,比如?USER?殖卑、?PASSWORD?站削、?HOST?等等。想了解更多數(shù)據(jù)庫設(shè)置方面的內(nèi)容孵稽,請(qǐng)看文檔:DATABASES?许起。

SQLite 以外的其它數(shù)據(jù)庫

如果你使用了 SQLite 以外的數(shù)據(jù)庫,請(qǐng)確認(rèn)在使用前已經(jīng)創(chuàng)建了數(shù)據(jù)庫菩鲜。你可以通過在你的數(shù)據(jù)庫交互式命令行中使用 "CREATE?DATABASE?database_name;" 命令來完成這件事园细。

另外,還要確保該數(shù)據(jù)庫用戶中提供?mysite/settings.py?具有 "create database" 權(quán)限接校。這使得自動(dòng)創(chuàng)建的?test database?能被以后的教程使用猛频。

如果你使用 SQLite,那么你不需要在使用前做任何事——數(shù)據(jù)庫會(huì)在需要的時(shí)候自動(dòng)創(chuàng)建。

編輯?mysite/settings.py?文件前鹿寻,先設(shè)置?TIME_ZONE?為你自己時(shí)區(qū)睦柴。

此外,關(guān)注一下文件頭部的?INSTALLED_APPS?設(shè)置項(xiàng)毡熏。這里包括了會(huì)在你項(xiàng)目中啟用的所有 Django 應(yīng)用坦敌。應(yīng)用能在多個(gè)項(xiàng)目中使用,你也可以打包并且發(fā)布應(yīng)用痢法,讓別人使用它們狱窘。

通常,?INSTALLED_APPS?默認(rèn)包括了以下 Django 的自帶應(yīng)用:

django.contrib.admin?-- 管理員站點(diǎn)疯暑, 你很快就會(huì)使用它训柴。

django.contrib.auth?-- 認(rèn)證授權(quán)系統(tǒng)哑舒。

django.contrib.contenttypes?-- 內(nèi)容類型框架妇拯。

django.contrib.sessions?-- 會(huì)話框架。

django.contrib.messages?-- 消息框架洗鸵。

django.contrib.staticfiles?-- 管理靜態(tài)文件的框架越锈。

這些應(yīng)用被默認(rèn)啟用是為了給常規(guī)項(xiàng)目提供方便。

默認(rèn)開啟的某些應(yīng)用需要至少一個(gè)數(shù)據(jù)表膘滨,所以甘凭,在使用他們之前需要在數(shù)據(jù)庫中創(chuàng)建一些表。請(qǐng)執(zhí)行以下命令:

$python manage.py migrate

這個(gè)?migrate?命令檢查?INSTALLED_APPS?設(shè)置火邓,為其中的每個(gè)應(yīng)用創(chuàng)建需要的數(shù)據(jù)表丹弱,至于具體會(huì)創(chuàng)建什么,這取決于你的?mysite/settings.py?設(shè)置文件和每個(gè)應(yīng)用的數(shù)據(jù)庫遷移文件(我們稍后會(huì)介紹這個(gè))铲咨。這個(gè)命令所執(zhí)行的每個(gè)遷移操作都會(huì)在終端中顯示出來躲胳。如果你感興趣的話,運(yùn)行你數(shù)據(jù)庫的命令行工具纤勒,并輸入?\dt?(PostgreSQL)坯苹,?SHOW?TABLES;?(MySQL),?.schema?(SQLite)或者?SELECT?TABLE_NAME?FROM?USER_TABLES;?(Oracle) 來看看 Django 到底創(chuàng)建了哪些表摇天。

寫給極簡主義者

就像之前說的粹湃,為了方便大多數(shù)項(xiàng)目,我們默認(rèn)激活了一些應(yīng)用泉坐,但并不是每個(gè)人都需要它們为鳄。如果你不需要某個(gè)或某些應(yīng)用,你可以在運(yùn)行?migrate?前毫無顧慮地從?INSTALLED_APPS?里注釋或者刪除掉它們腕让。?migrate?命令只會(huì)為在?INSTALLED_APPS?里聲明了的應(yīng)用進(jìn)行數(shù)據(jù)庫遷移孤钦。

創(chuàng)建模型?

在 Django 里寫一個(gè)數(shù)據(jù)庫驅(qū)動(dòng)的 Web 應(yīng)用的第一步是定義模型 - 也就是數(shù)據(jù)庫結(jié)構(gòu)設(shè)計(jì)和附加的其它元數(shù)據(jù)。

設(shè)計(jì)哲學(xué)

模型是真實(shí)數(shù)據(jù)的簡單明確的描述。它包含了儲(chǔ)存的數(shù)據(jù)所必要的字段和行為司训。Django 遵循?DRY Principle?构捡。它的目標(biāo)是你只需要定義數(shù)據(jù)模型,然后其它的雜七雜八代碼你都不用關(guān)心壳猜,它們會(huì)自動(dòng)從模型生成勾徽。

來介紹一下遷移 - 舉個(gè)例子,不像 Ruby On Rails统扳,Django 的遷移代碼是由你的模型文件自動(dòng)生成的喘帚,它本質(zhì)上只是個(gè)歷史記錄,Django 可以用它來進(jìn)行數(shù)據(jù)庫的滾動(dòng)更新咒钟,通過這種方式使其能夠和當(dāng)前的模型匹配吹由。

在這個(gè)簡單的投票應(yīng)用中,需要?jiǎng)?chuàng)建兩個(gè)模型:問題?Question?和選項(xiàng)?Choice朱嘴。Question?模型包括問題描述和發(fā)布時(shí)間倾鲫。Choice?模型有兩個(gè)字段,選項(xiàng)描述和當(dāng)前得票數(shù)萍嬉。每個(gè)選項(xiàng)屬于一個(gè)問題乌昔。

這些概念可以通過一個(gè)簡單的 Python 類來描述。按照下面的例子來編輯?polls/models.py?文件:

polls/models.py

fromdjango.dbimportmodelsclassQuestion(models.Model):question_text=models.CharField(max_length=200)pub_date=models.DateTimeField('date published')classChoice(models.Model):question=models.ForeignKey(Question,on_delete=models.CASCADE)choice_text=models.CharField(max_length=200)votes=models.IntegerField(default=0)

代碼非常直白壤追。每個(gè)模型被表示為?django.db.models.Model?類的子類磕道。每個(gè)模型有一些類變量,它們都表示模型里的一個(gè)數(shù)據(jù)庫字段行冰。

每個(gè)字段都是?Field?類的實(shí)例 - 比如溺蕉,字符字段被表示為?CharField?,日期時(shí)間字段被表示為?DateTimeField?悼做。這將告訴 Django 每個(gè)字段要處理的數(shù)據(jù)類型疯特。

每個(gè)?Field?類實(shí)例變量的名字(例如?question_text?或?pub_date?)也是字段名,所以最好使用對(duì)機(jī)器友好的格式贿堰。你將會(huì)在 Python 代碼里使用它們辙芍,而數(shù)據(jù)庫會(huì)將它們作為列名。

你可以使用可選的選項(xiàng)來為?Field?定義一個(gè)人類可讀的名字羹与。這個(gè)功能在很多 Django 內(nèi)部組成部分中都被使用了故硅,而且作為文檔的一部分。如果某個(gè)字段沒有提供此名稱纵搁,Django 將會(huì)使用對(duì)機(jī)器友好的名稱吃衅,也就是變量名。在上面的例子中腾誉,我們只為Question.pub_date?定義了對(duì)人類友好的名字徘层。對(duì)于模型內(nèi)的其它字段峻呕,它們的機(jī)器友好名也會(huì)被作為人類友好名使用。

定義某些?Field?類實(shí)例需要參數(shù)趣效。例如?CharField?需要一個(gè)?max_length?參數(shù)瘦癌。這個(gè)參數(shù)的用處不止于用來定義數(shù)據(jù)庫結(jié)構(gòu),也用于驗(yàn)證數(shù)據(jù)跷敬,我們稍后將會(huì)看到這方面的內(nèi)容讯私。

Field?也能夠接收多個(gè)可選參數(shù);在上面的例子中:我們將?votes?的?default?也就是默認(rèn)值西傀,設(shè)為0斤寇。

注意在最后,我們使用?ForeignKey?定義了一個(gè)關(guān)系拥褂。這將告訴 Django娘锁,每個(gè)?Choice?對(duì)象都關(guān)聯(lián)到一個(gè)?Question?對(duì)象。Django 支持所有常用的數(shù)據(jù)庫關(guān)系:多對(duì)一饺鹃、多對(duì)多和一對(duì)一莫秆。

激活模型?

上面的一小段用于創(chuàng)建模型的代碼給了 Django 很多信息,通過這些信息尤慰,Django 可以:

為這個(gè)應(yīng)用創(chuàng)建數(shù)據(jù)庫 schema(生成?CREATE?TABLE?語句)馏锡。

創(chuàng)建可以與?Question?和?Choice?對(duì)象進(jìn)行交互的 Python 數(shù)據(jù)庫 API雷蹂。

但是首先得把?polls?應(yīng)用安裝到我們的項(xiàng)目里伟端。

設(shè)計(jì)哲學(xué)

Django 應(yīng)用是“可插拔”的。你可以在多個(gè)項(xiàng)目中使用同一個(gè)應(yīng)用责蝠。除此之外霜医,你還可以發(fā)布自己的應(yīng)用肴敛,因?yàn)樗鼈儾⒉粫?huì)被綁定到當(dāng)前安裝的 Django 上。

為了在我們的工程中包含這個(gè)應(yīng)用镀梭,我們需要在配置類?INSTALLED_APPS?中添加設(shè)置报账。因?yàn)?PollsConfig?類寫在文件?polls/apps.py?中榜晦,所以它的點(diǎn)式路徑是?'polls.apps.PollsConfig'芽隆。在文件?mysite/settings.py?中?INSTALLED_APPS?子項(xiàng)添加點(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 項(xiàng)目會(huì)包含?polls?應(yīng)用腕扶。接著運(yùn)行下面的命令:

$python manage.py makemigrations polls

你將會(huì)看到類似于下面這樣的輸出:

Migrations for 'polls':? polls/migrations/0001_initial.py:? ? - Create model Choice? ? - Create model Question? ? - Add field question to choice

通過運(yùn)行?makemigrations?命令半抱,Django 會(huì)檢測(cè)你對(duì)模型文件的修改(在這種情況下,你已經(jīng)取得了新的)史简,并且把修改的部分儲(chǔ)存為一次?遷移圆兵。

遷移是 Django 對(duì)于模型定義(也就是你的數(shù)據(jù)庫結(jié)構(gòu))的變化的儲(chǔ)存形式 - 沒那么玄乎,它們其實(shí)也只是一些你磁盤上的文件超凳。如果你想的話轮傍,你可以閱讀一下你模型的遷移數(shù)據(jù),它被儲(chǔ)存在?polls/migrations/0001_initial.py?里挥下。別擔(dān)心棚瘟,你不需要每次都閱讀遷移文件庄蹋,但是它們被設(shè)計(jì)成人類可讀的形式限书,這是為了便于你手動(dòng)修改它們倦西。

Django 有一個(gè)自動(dòng)執(zhí)行數(shù)據(jù)庫遷移并同步管理你的數(shù)據(jù)庫結(jié)構(gòu)的命令 - 這個(gè)命令是?migrate,我們馬上就會(huì)接觸它 - 但是首先卤档,讓我們看看遷移命令會(huì)執(zhí)行哪些 SQL 語句。sqlmigrate?命令接收一個(gè)遷移的名稱哨免,然后返回對(duì)應(yīng)的 SQL:

$python manage.py sqlmigrate polls0001

你將會(huì)看到類似下面這樣的輸出(我把輸出重組成了人類可讀的格式):

BEGIN;---- Create model Choice--CREATETABLE"polls_choice"("id"serialNOTNULLPRIMARYKEY,"choice_text"varchar(200)NOTNULL,"votes"integerNOTNULL);---- Create model Question--CREATETABLE"polls_question"("id"serialNOTNULLPRIMARYKEY,"question_text"varchar(200)NOTNULL,"pub_date"timestampwithtimezoneNOTNULL);---- Add field question to choice--ALTERTABLE"polls_choice"ADDCOLUMN"question_id"integerNOTNULL;ALTERTABLE"polls_choice"ALTERCOLUMN"question_id"DROPDEFAULT;CREATEINDEX"polls_choice_7aa0f6ee"ON"polls_choice"("question_id");ALTERTABLE"polls_choice"ADDCONSTRAINT"polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"FOREIGNKEY("question_id")REFERENCES"polls_question"("id")DEFERRABLEINITIALLYDEFERRED;COMMIT;

請(qǐng)注意以下幾點(diǎn):

輸出的內(nèi)容和你使用的數(shù)據(jù)庫有關(guān)载荔,上面的輸出示例使用的是 PostgreSQL。

數(shù)據(jù)庫的表名是由應(yīng)用名(polls)和模型名的小寫形式(?question?和?choice)連接而來。(如果需要徘钥,你可以自定義此行為呈础。)

主鍵(IDs)會(huì)被自動(dòng)創(chuàng)建沙廉。(當(dāng)然,你也可以自定義巨税。)

默認(rèn)的,Django 會(huì)在外鍵字段名后追加字符串?"_id"?果元。(同樣,這也可以自定義阅畴。)

外鍵關(guān)系由?FOREIGN?KEY?生成监署。你不用關(guān)心?DEFERRABLE?部分,它只是告訴 PostgreSQL晓避,請(qǐng)?jiān)谑聞?wù)全都執(zhí)行完之后再創(chuàng)建外鍵關(guān)系。

生成的 SQL 語句是為你所用的數(shù)據(jù)庫定制的吼句,所以那些和數(shù)據(jù)庫有關(guān)的字段類型驹愚,比如?auto_increment?(MySQL)、?serial(PostgreSQL)和?integer?primary?key?autoincrement?(SQLite)味廊,Django 會(huì)幫你自動(dòng)處理蒸甜。那些和引號(hào)相關(guān)的事情 - 例如,是使用單引號(hào)還是雙引號(hào) - 也一樣會(huì)被自動(dòng)處理余佛。

這個(gè)?sqlmigrate?命令并沒有真正在你的數(shù)據(jù)庫中的執(zhí)行遷移 - 它只是把命令輸出到屏幕上柠新,讓你看看 Django 認(rèn)為需要執(zhí)行哪些 SQL 語句。這在你想看看 Django 到底準(zhǔn)備做什么辉巡,或者當(dāng)你是數(shù)據(jù)庫管理員恨憎,需要寫腳本來批量處理數(shù)據(jù)庫時(shí)會(huì)很有用。

如果你感興趣,你也可以試試運(yùn)行?python?manage.py?check?;這個(gè)命令幫助你檢查項(xiàng)目中的問題今瀑,并且在檢查過程中不會(huì)對(duì)數(shù)據(jù)庫進(jìn)行任何操作。

現(xiàn)在错邦,再次運(yùn)行?migrate?命令毛仪,在數(shù)據(jù)庫里創(chuàng)建新定義的模型的數(shù)據(jù)表:

$python manage.py migrateOperations to perform:? Apply all migrations: admin, auth, contenttypes, polls, sessionsRunning migrations:? Rendering model states... DONE? Applying polls.0001_initial... OK

這個(gè)?migrate?命令選中所有還沒有執(zhí)行過的遷移(Django 通過在數(shù)據(jù)庫中創(chuàng)建一個(gè)特殊的表?django_migrations?來跟蹤執(zhí)行過哪些遷移)并應(yīng)用在數(shù)據(jù)庫上 - 也就是將你對(duì)模型的更改同步到數(shù)據(jù)庫結(jié)構(gòu)上。

遷移是非常強(qiáng)大的功能,它能讓你在開發(fā)過程中持續(xù)的改變數(shù)據(jù)庫結(jié)構(gòu)而不需要重新刪除和創(chuàng)建表 - 它專注于使數(shù)據(jù)庫平滑升級(jí)而不會(huì)丟失數(shù)據(jù)。我們會(huì)在后面的教程中更加深入的學(xué)習(xí)這部分內(nèi)容,現(xiàn)在疯搅,你只需要記住,改變模型需要這三步:

編輯?models.py?文件,改變模型喇完。

運(yùn)行?python?manage.py?makemigrations?為模型的改變生成遷移文件坏逢。

運(yùn)行?python?manage.py?migrate?來應(yīng)用數(shù)據(jù)庫遷移事秀。

數(shù)據(jù)庫遷移被分解成生成和應(yīng)用兩個(gè)命令是為了讓你能夠在代碼控制系統(tǒng)上提交遷移數(shù)據(jù)并使其能在多個(gè)應(yīng)用里使用窘疮;這不僅僅會(huì)讓開發(fā)更加簡單身冬,也給別的開發(fā)者和生產(chǎn)環(huán)境中的使用帶來方便茁影。

通過閱讀文檔?Django 后臺(tái)文檔?宙帝,你可以獲得關(guān)于?manage.py?工具的更多信息。

初試 API?

現(xiàn)在讓我們進(jìn)入交互式 Python 命令行或颊,嘗試一下 Django 為你創(chuàng)建的各種 API棠隐。通過以下命令打開 Python 命令行:

$python manage.py shell

我們使用這個(gè)命令而不是簡單的使用 "Python" 是因?yàn)?manage.py?會(huì)設(shè)置?DJANGO_SETTINGS_MODULE?環(huán)境變量煞茫,這個(gè)變量會(huì)讓 Django 根據(jù)?mysite/settings.py?文件來設(shè)置 Python 包的導(dǎo)入路徑。

當(dāng)你成功進(jìn)入命令行后摄凡,來試試?database API?吧:

>>> frompolls.modelsimportChoice,Question# Import the model classes we just wrote.# No questions are in the system yet.>>> Question.objects.all()<QuerySet []># Create a new Question.# Support for time zones is enabled in the default settings file, so# Django expects a datetime with tzinfo for pub_date. Use timezone.now()# instead of datetime.datetime.now() and it will do the right thing.>>> fromdjango.utilsimporttimezone>>> q=Question(question_text="What's new?",pub_date=timezone.now())# Save the object into the database. You have to call save() explicitly.>>> q.save()# Now it has an ID.>>> q.id1# Access model field values via Python attributes.>>> q.question_text"What's new?">>> q.pub_datedatetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)# Change values by changing the attributes, then calling save().>>> q.question_text="What's up?">>> q.save()# objects.all() displays all the questions in the database.>>> Question.objects.all()<QuerySet [<Question: Question object (1)>]>

等等续徽。<Question:?Question?object?(1)>?對(duì)于我們了解這個(gè)對(duì)象的細(xì)節(jié)沒什么幫助。讓我們通過編輯?Question?模型的代碼(位于?polls/models.py?中)來修復(fù)這個(gè)問題亲澡。給?Question?和?Choice?增加?__str__()?方法钦扭。

polls/models.py

fromdjango.dbimportmodelsclassQuestion(models.Model):# ...def__str__(self):returnself.question_textclassChoice(models.Model):# ...def__str__(self):returnself.choice_text

給模型增加?__str__()?方法是很重要的,這不僅僅能給你在命令行里使用帶來方便床绪,Django 自動(dòng)生成的 admin 里也使用這個(gè)方法來表示對(duì)象客情。

注意:這些都是常規(guī)的 Python方法。讓我們添加一個(gè)自定義的方法会涎,這只是為了演示:

polls/models.py

importdatetimefromdjango.dbimportmodelsfromdjango.utilsimporttimezoneclassQuestion(models.Model):# ...defwas_published_recently(self):returnself.pub_date>=timezone.now()-datetime.timedelta(days=1)

新加入的?import?datetime?和?from?django.utils?import?timezone?分別導(dǎo)入了 Python 的標(biāo)準(zhǔn)?datetime?模塊和 Django 中和時(shí)區(qū)相關(guān)的?django.utils.timezone?工具模塊裹匙。如果你不太熟悉 Python 中的時(shí)區(qū)處理,看看?時(shí)區(qū)支持文檔?吧末秃。

保存文件然后通過?python?manage.py?shell?命令再次打開 Python 交互式命令行:

>>> frompolls.modelsimportChoice,Question# Make sure our __str__() addition worked.>>> Question.objects.all()<QuerySet [<Question: What's up?>]># Django provides a rich database lookup API that's entirely driven by# keyword arguments.>>> Question.objects.filter(id=1)<QuerySet [<Question: What's up?>]>>>> Question.objects.filter(question_text__startswith='What')<QuerySet [<Question: What's up?>]># Get the question that was published this year.>>> fromdjango.utilsimporttimezone>>> current_year=timezone.now().year>>> Question.objects.get(pub_date__year=current_year)<Question: What's up?># Request an ID that doesn't exist, this will raise an exception.>>> Question.objects.get(id=2)Traceback (most recent call last):...DoesNotExist:Question matching query does not exist.# Lookup by a primary key is the most common case, so Django provides a# shortcut for primary-key exact lookups.# The following is identical to Question.objects.get(id=1).>>> Question.objects.get(pk=1)<Question: What's up?># Make sure our custom method worked.>>> q=Question.objects.get(pk=1)>>> q.was_published_recently()True# Give the Question a couple of Choices. The create call constructs a new# Choice object, does the INSERT statement, adds the choice to the set# of available choices and returns the new Choice object. Django creates# a set to hold the "other side" of a ForeignKey relation# (e.g. a question's choice) which can be accessed via the API.>>> q=Question.objects.get(pk=1)# Display any choices from the related object set -- none so far.>>> q.choice_set.all()<QuerySet []># Create three choices.>>> 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 objects have API access to their related Question objects.>>> c.question<Question: What's up?># And vice versa: Question objects get access to Choice objects.>>> 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.# Find all Choices for any question whose pub_date is in this year# (reusing the 'current_year' variable we created above).>>> Choice.objects.filter(question__pub_date__year=current_year)<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]># Let's delete one of the choices. Use delete() for that.>>> c=q.choice_set.filter(choice_text__startswith='Just hacking')>>> c.delete()

閱讀?訪問關(guān)系對(duì)象?文檔可以獲取關(guān)于數(shù)據(jù)庫關(guān)系的更多內(nèi)容概页。想知道關(guān)于雙下劃線的更多用法,參見?查找字段?文檔练慕。數(shù)據(jù)庫 API 的所有細(xì)節(jié)可以在?數(shù)據(jù)庫 API 參考?文檔中找到惰匙。

介紹 Django 管理頁面?

設(shè)計(jì)哲學(xué)

為你的員工或客戶生成一個(gè)用戶添加,修改和刪除內(nèi)容的后臺(tái)是一項(xiàng)缺乏創(chuàng)造性和乏味的工作铃将。因此项鬼,Django 全自動(dòng)地根據(jù)模型創(chuàng)建后臺(tái)界面。

Django 產(chǎn)生于一個(gè)公眾頁面和內(nèi)容發(fā)布者頁面完全分離的新聞?lì)愓军c(diǎn)的開發(fā)過程中劲阎。站點(diǎn)管理人員使用管理系統(tǒng)來添加新聞绘盟、事件和體育時(shí)訊等,這些添加的內(nèi)容被顯示在公眾頁面上悯仙。Django 通過為站點(diǎn)管理人員創(chuàng)建統(tǒng)一的內(nèi)容編輯界面解決了這個(gè)問題龄毡。

管理界面不是為了網(wǎng)站的訪問者,而是為管理者準(zhǔn)備的锡垄。

創(chuàng)建一個(gè)管理員賬號(hào)?

首先沦零,我們得創(chuàng)建一個(gè)能登錄管理頁面的用戶。請(qǐng)運(yùn)行下面的命令:

$python manage.py createsuperuser

鍵入你想要使用的用戶名货岭,然后按下回車鍵:

Username: admin

然后提示你輸入想要使用的郵件地址:

Email address: admin@example.com

最后一步是輸入密碼路操。你會(huì)被要求輸入兩次密碼疾渴,第二次的目的是為了確認(rèn)第一次輸入的確實(shí)是你想要的密碼。

Password: **********Password (again): *********Superuser created successfully.

啟動(dòng)開發(fā)服務(wù)器?

Django 的管理界面默認(rèn)就是啟用的屯仗。讓我們啟動(dòng)開發(fā)服務(wù)器搞坝,看看它到底是什么樣的。

如果開發(fā)服務(wù)器未啟動(dòng)祭钉,用以下命令啟動(dòng)它:

$python manage.py runserver

現(xiàn)在瞄沙,打開瀏覽器,轉(zhuǎn)到你本地域名的 "/admin/" 目錄慌核, -- 比如 "http://127.0.0.1:8000/admin/" 。你應(yīng)該會(huì)看見管理員登錄界面:

因?yàn)?翻譯?功能默認(rèn)是開著的申尼,所以登錄界面可能會(huì)使用你的語言垮卓,取決于你瀏覽器的設(shè)置和 Django 是否擁有你語言的翻譯。

進(jìn)入管理站點(diǎn)頁面?

現(xiàn)在师幕,試著使用你在上一步中創(chuàng)建的超級(jí)用戶來登錄粟按。然后你將會(huì)看到 Django 管理頁面的索引頁:

你將會(huì)看到幾種可編輯的內(nèi)容:組和用戶。它們是由?django.contrib.auth?提供的霹粥,這是 Django 開發(fā)的認(rèn)證框架灭将。

向管理頁面中加入投票應(yīng)用?

但是我們的投票應(yīng)用在哪呢?它沒在索引頁面里顯示后控。

只需要做一件事:我們得告訴管理頁面庙曙,問題?Question?對(duì)象需要被管理。打開?polls/admin.py?文件浩淘,把它編輯成下面這樣:

polls/admin.py

fromdjango.contribimportadminfrom.modelsimportQuestionadmin.site.register(Question)

體驗(yàn)便捷的管理功能?

現(xiàn)在我們向管理頁面注冊(cè)了問題?Question?類捌朴。Django 知道它應(yīng)該被顯示在索引頁里:

點(diǎn)擊 "Questions" 。現(xiàn)在看到是問題 "Questions" 對(duì)象的列表 "change list" 张抄。這個(gè)界面會(huì)顯示所有數(shù)據(jù)庫里的問題 Question 對(duì)象砂蔽,你可以選擇一個(gè)來修改。這里現(xiàn)在有我們?cè)谏弦徊糠种袆?chuàng)建的 “What's up?” 問題署惯。

點(diǎn)擊 “What's up?” 來編輯這個(gè)問題(Question)對(duì)象:

注意事項(xiàng):

這個(gè)表單是從問題?Question?模型中自動(dòng)生成的

不同的字段類型(日期時(shí)間字段?DateTimeField?左驾、字符字段?CharField)會(huì)生成對(duì)應(yīng)的 HTML 輸入控件。每個(gè)類型的字段都知道它們?cè)撊绾卧诠芾眄撁胬镲@示自己极谊。

每個(gè)日期時(shí)間字段?DateTimeField?都有 JavaScript 寫的快捷按鈕诡右。日期有轉(zhuǎn)到今天(Today)的快捷按鈕和一個(gè)彈出式日歷界面。時(shí)間有設(shè)為現(xiàn)在(Now)的快捷按鈕和一個(gè)列出常用時(shí)間的方便的彈出式列表怀酷。

頁面的底部提供了幾個(gè)選項(xiàng):

保存(Save) - 保存改變稻爬,然后返回對(duì)象列表。

保存并繼續(xù)編輯(Save and continue editing) - 保存改變蜕依,然后重新載入當(dāng)前對(duì)象的修改界面桅锄。

保存并新增(Save and add another) - 保存改變琉雳,然后添加一個(gè)新的空對(duì)象并載入修改界面。

刪除(Delete) - 顯示一個(gè)確認(rèn)刪除頁面友瘤。

如果顯示的 “發(fā)布日期(Date Published)” 和你在?教程 1?里創(chuàng)建它們的時(shí)間不一致翠肘,這意味著你可能沒有正確的設(shè)置?TIME_ZONE?。改變?cè)O(shè)置辫秧,然后重新載入頁面看看是否顯示了正確的值束倍。

通過點(diǎn)擊 “今天(Today)” 和 “現(xiàn)在(Now)” 按鈕改變 “發(fā)布日期(Date Published)”。然后點(diǎn)擊 “保存并繼續(xù)編輯(Save and add another)”按鈕盟戏。然后點(diǎn)擊右上角的 “歷史(History)”按鈕绪妹。你會(huì)看到一個(gè)列出了所有通過 Django 管理頁面對(duì)當(dāng)前對(duì)象進(jìn)行的改變的頁面,其中列出了時(shí)間戳和進(jìn)行修改操作的用戶名:

當(dāng)你熟悉了數(shù)據(jù)庫 API 之后柿究,你就可以開始閱讀?教程第 3 部分?邮旷,下一部分我們將會(huì)學(xué)習(xí)如何為投票應(yīng)用添加更多視圖。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蝇摸,一起剝皮案震驚了整個(gè)濱河市婶肩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌貌夕,老刑警劉巖律歼,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異啡专,居然都是意外死亡险毁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門植旧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辱揭,“玉大人,你說我怎么就攤上這事病附∥是裕” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵完沪,是天一觀的道長域庇。 經(jīng)常有香客問我,道長覆积,這世上最難降的妖魔是什么听皿? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮宽档,結(jié)果婚禮上尉姨,老公的妹妹穿的比我還像新娘。我一直安慰自己吗冤,他們只是感情好又厉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布九府。 她就那樣靜靜地躺著,像睡著了一般覆致。 火紅的嫁衣襯著肌膚如雪侄旬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天煌妈,我揣著相機(jī)與錄音儡羔,去河邊找鬼。 笑死璧诵,一個(gè)胖子當(dāng)著我的面吹牛汰蜘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腮猖,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鉴扫,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了澈缺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤炕婶,失蹤者是張志新(化名)和其女友劉穎姐赡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柠掂,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡项滑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涯贞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枪狂。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宋渔,靈堂內(nèi)的尸體忽然破棺而出州疾,到底是詐尸還是另有隱情,我是刑警寧澤皇拣,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布严蓖,位于F島的核電站,受9級(jí)特大地震影響氧急,放射性物質(zhì)發(fā)生泄漏颗胡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一吩坝、第九天 我趴在偏房一處隱蔽的房頂上張望毒姨。 院中可真熱鬧,春花似錦钉寝、人聲如沸弧呐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泉懦。三九已至稿黍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崩哩,已是汗流浹背巡球。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邓嘹,地道東北人酣栈。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像汹押,于是被迫代替她去往敵國和親矿筝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容