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

編寫你的第一個(gè) Django 程序 第2部分

本教程上接 教程 第1部分 。 我們將繼續(xù)開發(fā) Web-poll 應(yīng)用,并且專注在 Django 的 自動生成的管理網(wǎng)站上。

哲理

為你的員工或客戶生成添加、修改和刪除內(nèi)容的管理性網(wǎng)站是個(gè)單調(diào)乏味的工作。 出于這個(gè)原因,Django 根據(jù)模型完全自動化創(chuàng)建管理界面。

Django 是在新聞編輯室環(huán)境下編寫的,“內(nèi)容發(fā)表者”和“公共”網(wǎng)站之間有 非常明顯的界線。網(wǎng)站管理員使用這個(gè)系統(tǒng)來添加新聞、事件、體育成績等等, 而這些內(nèi)容會在公共網(wǎng)站上顯示出來。Django 解決了為網(wǎng)站管理員創(chuàng)建統(tǒng)一 的管理界面用以編輯內(nèi)容的問題。

管理界面不是讓網(wǎng)站訪問者使用的。它是為網(wǎng)站管理員準(zhǔn)備的。

啟用管理網(wǎng)站

  • 默認(rèn)情況下 Django 管理網(wǎng)站是不啟用的 – 它是可選的。 要啟用管理網(wǎng)站,需要做三件事:
  • 在 INSTALLED_APPS 設(shè)置中取消 "django.contrib.admin" 的注釋。
  • 運(yùn)行 python manage.py syncdb 命令。既然你添加了新應(yīng)用到 INSTALLED_APPS 中,數(shù)據(jù)庫表就需要更新。
  • 編輯你的 mysite/urls.py 文件并且將有關(guān)管理的行取消注釋 – 共有三行取消了注釋。該文件是 URLconf ;我們將在下一個(gè)教程中深入探討 URLconfs 。現(xiàn)在,你需要知道的是它將 URL 映射到應(yīng)用。最后你擁有的 urls.py 文件看起來像這樣:
from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', '{{ project_name }}.views.home', name='home'),
    # url(r'^{{ project_name }}/', include('{{ project_name }}.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    url(r'^admin/', include(admin.site.urls)),
)

( 粗體顯示的行就是那些需要取消注釋的行。)

啟動開發(fā)服務(wù)器

讓我們啟動開發(fā)服務(wù)器并瀏覽管理網(wǎng)站。

回想下教程的第一部分,像如下所示啟動你的開發(fā)服務(wù)器:

python manage.py runserver

現(xiàn)在,打開一個(gè)瀏覽器并在本地域名上訪問 “/admin/” – 例如 http://127.0.0.1:8000/admin/ 。你將看到管理員的登錄界面:

和你看到的不一樣?

如果看到這,而不是上面的登錄界面,那你應(yīng)該得到一個(gè)類似如下所示的錯(cuò)誤頁面報(bào)告:

ImportError at /admin/ cannot import name patterns ...

那么你很可能使用的 Django 版本不符合本教程的版本。 你可以切換到對應(yīng)的舊版本教程去或者更新到較新的 Django 版本。

進(jìn)入管理網(wǎng)站

現(xiàn)在嘗試登錄進(jìn)去。(還記得嗎?在本教程的第一部分時(shí)你創(chuàng)建過一個(gè)超級用戶的帳號。如果你沒有創(chuàng)建或忘記了密碼,你可以 另外創(chuàng)建一個(gè) 。) 你將看到 Djaong 的管理索引頁:

你將看到一些可編輯的內(nèi)容,包括 groups ,users 和 sites 。這些都是 Django 默認(rèn)情況下自帶的核心功能。

使 poll 應(yīng)用的數(shù)據(jù)在管理網(wǎng)站中可編輯

但是 poll 應(yīng)用在哪? 它可是沒有在管理網(wǎng)站的首頁上顯示啊。

只需要做一件事:我們需要告訴管理網(wǎng)站 Poll 對象要有一個(gè)管理界面。為此,我們在你的 polls 目錄下創(chuàng)建一個(gè)名為 admin.py 的文件,并添加如下內(nèi)容::

from django.contrib import admin
from polls.models import Poll
admin.site.register(Poll)

你需要重啟開發(fā)服務(wù)器才能看到變化。通常情況下,你每次修改過一個(gè)文件后開發(fā) 服務(wù)器都會自動載入,但是創(chuàng)建一個(gè)新文件卻不會觸發(fā)自動載入的邏輯。

探索管理功能

現(xiàn)在我們已經(jīng)注冊了 Poll ,那 Django 就知道了要在管理網(wǎng)站的首頁上顯示出來:

點(diǎn)擊 “Polls” ?,F(xiàn)在你在 polls 的 “更改列表” 頁。該頁 顯示了數(shù)據(jù)庫中所有的 polls 可讓你選中一個(gè)進(jìn)行編輯。 有個(gè) “What’s up?” poll 是我們在第一個(gè)教程中創(chuàng)建的:

點(diǎn)擊這個(gè)”What’s up?” 的 poll 進(jìn)行編輯:

這有些注意事項(xiàng):

  • 這的表單是根據(jù) Poll 模型自動生成的。
  • 不同模型的字段類型 (DateTimeField, CharField) 會對應(yīng)的相應(yīng)的 HTML 輸入控件。 每一種類型的字段 Djaong 管理網(wǎng)站都知道如何顯示它們。
  • 每個(gè) DateTimeField 都會有個(gè)方便的 JavaScript 快捷方式。日期有一個(gè) “Today” 快捷方式和彈出式日歷,而時(shí)間有個(gè) “Now” 快捷方式和一個(gè)列出了常用時(shí)間選項(xiàng)的彈出式窗口。

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

  • Save – 保存更改并返回到當(dāng)前類型的對象的更改列表頁面。
  • Save and continue editing – 保存更改并重新載入當(dāng)前對象的管理界面。
  • Save and add another – 保存更改并載入當(dāng)前對象類型的新的空白表單。
  • Delete – 顯示刪除確認(rèn)頁。

如果 “Date published” 的值與你在第一部分教程時(shí)創(chuàng)建的 poll 的時(shí)間不符,這可能 意味著你忘記了將 TIME_ZONE 設(shè)置成正確的值了。修改正確后再重啟載入頁面 來檢查值是否正確。

分別點(diǎn)擊 “Today” 和 “Now” 快捷方式來修改 “Date published” 的值。 然后點(diǎn)擊 “Save and continue editing” 。最后點(diǎn)擊右上角的 “History” 。 你將看到一頁列出了通過 Django 管理界面對此對象所做的全部更改的清單的頁面, 包含有時(shí)間戳和修改人的姓名等信息:

自定義管理表單

花些時(shí)間感嘆一下吧,你沒寫什么代碼就擁有了這一切。通過 admin.site.register(Poll) 注冊了 Poll 模型,Django 就能構(gòu)造一個(gè)默認(rèn)的 表單。通常情況下,你將要自定義管理表單的外觀和功能。這樣的話你就需要在注冊對象 時(shí)告訴 Django 對應(yīng)的配置。

讓我們來看看如何在編輯表單上給字段重新排序。將 admin.site.register(Poll) 這行替換成::

class PollAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question']

admin.site.register(Poll, PollAdmin)

你將遵循這個(gè)模式 – 創(chuàng)建一個(gè)模型的管理對象,將它作為 admin.site.register() 方法的第二個(gè)參數(shù)傳入 – 當(dāng)你需要為一個(gè)對象做管理界面配置的時(shí)候。

上面那特定的更改使得 “Publication date” 字段在 “Question” 字段之前:

僅有兩個(gè)字段不會令你印象深刻,但是對于有許多字段的管理表單時(shí),選擇一個(gè)直觀 的排序方式是一個(gè)重要的實(shí)用細(xì)節(jié)。

剛才所說的有許多字段的表單,你可能想將表單中的字段分割成 fieldsets ::

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Poll, PollAdmin)

在 fieldsets 中每一個(gè) tuple 的第一個(gè)元素就是 fieldset 的標(biāo)題。 下面是我們表單現(xiàn)在的樣子:

你可以為每個(gè) fieldset 指定 THML 樣式類。Django 提供了一個(gè) "collapse" 樣式類用于顯示初始時(shí)是收縮的 fieldset 。 當(dāng)你有一個(gè)包含一些不常用的長窗體時(shí)這是非常有用的

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
Fieldset is initially collapsed

添加關(guān)聯(lián)對象

Ok,現(xiàn)在我們有了 Poll 的管理頁面。但是一個(gè) Poll 擁有多個(gè) Choices ,而 該管理頁面并沒有顯示對應(yīng)的 choices 。

是的。

我們有兩種方法來解決這個(gè)問題。第一種就像剛才 Poll 那樣在管理網(wǎng)站上 注冊 Choice 。這很簡單:

from polls.models import Choice

admin.site.register(Choice)

現(xiàn)在 “Choices” 在 Django 管理網(wǎng)站上是一個(gè)可用的選項(xiàng)了。”Add choice” 表單 看起來像這樣:

該表單中,Poll 字段是一個(gè)包含了數(shù)據(jù)庫中每個(gè) poll 的選擇框。 Django 知道 ForeignKey 在管理網(wǎng)站中以 <select> 框顯示。在本例中,選擇框中僅存在一個(gè) poll 。

另外請注意 Poll 旁邊的 “Add Another” 鏈接。每個(gè)有 ForeignKey 的對象關(guān)聯(lián)到其他對象都會得到這個(gè)鏈接。 當(dāng)點(diǎn)擊 “Add Another” 時(shí),你將會獲得一個(gè) “Add poll” 表單的彈出窗口。 如果你在窗口中添加了一 poll 并點(diǎn)擊了 “Save” 按鈕, Django 會將 poll 保存至數(shù)據(jù)庫中并且動態(tài)的添加為你正在查看的 “Add choice” 表單中的 已選擇項(xiàng)。

但是,這真是一個(gè)低效的將 Choice 對象添加進(jìn)系統(tǒng)的方式。 如果在創(chuàng)建 Poll 對象時(shí)能夠直接添加一批 Choices 那會更好。 讓我們這樣做吧。

移除對 Choice 模型的 register() 方法調(diào)用 。然后,將 Poll 的注冊代碼 編輯為如下所示:

from django.contrib import admin
from polls.models import Choice, Poll

class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Poll, PollAdmin)

這將告訴 Django: “Choice 對象在 Poll 管理頁面中被編輯。 默認(rèn)情況下,提供 3 個(gè) choices 的字段空間。

載入 “Add poll” 頁面來看看,你可能需要重啟你的開發(fā)服務(wù)器:

它看起來像這樣:多了三個(gè)為關(guān)聯(lián) Choices 提供的輸入插槽 – 由 extra 指定 – 并且每次你在 “Change” 頁修改已經(jīng)創(chuàng)建的對象時(shí),都會另外獲得三個(gè)額外插槽。

在現(xiàn)有的三個(gè)插槽的底部,你會發(fā)現(xiàn)一個(gè) “Add another Choice” 鏈接。 如果你點(diǎn)擊它,一個(gè)新的插槽會被添加。如果想移除添加的插槽, 你可以點(diǎn)擊所添加的插槽的右上方的 X 。注意你不能移除原有的三個(gè)插槽。 此圖片中顯示了新增的插槽:

還有個(gè)小問題。為了顯示所有關(guān)聯(lián) Choice 對象的字段需要占用大量的 屏幕空間。為此,Django 提供了一個(gè)以表格方式顯示內(nèi)嵌有關(guān)聯(lián)對象的方式; 你只需要將 ChoiceInline 聲明改為如下所示:

class ChoiceInline(admin.TabularInline):
    #...

使用了 TabularInline 后(而不是 StackedInline) ,基于表的格式下相關(guān) 對象被顯示的更緊湊了:

需要注意的是有個(gè)額外的 “Delete?” 列允許保存時(shí)移除已保存過的行。

自定義管理界面的變更列表

現(xiàn)在 Poll 的管理界面看起來不錯(cuò)了,讓我們給 “chang list” 頁面做些調(diào)整 – 顯示系統(tǒng)中所有 polls 的頁面。

下面是現(xiàn)在的樣子:

默認(rèn)情況下, Django 顯示的是每個(gè)對象 str() 的結(jié)果。但是若是我們能夠 顯示每個(gè)字段的話有時(shí)會更有幫助的。要做到這一點(diǎn),需要使用 list_display 管理選項(xiàng),這是一個(gè) tuple ,包含了要顯示的字段名, 將會以列的形式在該對象的 chang lsit 頁上列出來::

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date')

效果再好的點(diǎn)話,讓我們把在第一部分教程中自定義的方法 was_published_recently 也包括進(jìn)來:

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date', 'was_published_recently')

現(xiàn)在 poll 的變更列表頁看起來像這樣:

你可以點(diǎn)擊列的標(biāo)題對這些值進(jìn)行排序 – 除了 was_published_recently 這一列,因?yàn)椴恢С指鶕?jù)方法輸出的內(nèi)容的排序。還要注意的是默認(rèn)情況下列的標(biāo)題是 was_published_recently ,就是方法名(將下劃線替換為空格),并且每一行以字符串形式輸出。

你可以通過給該方法 (在 models.py 內(nèi) ) 添加一些屬性來改善顯示效果,如下所示::

class Poll(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

再次編輯你的 admin.py 文件并添加一個(gè)改進(jìn) Poll 的 change list 頁面效果的功能: 篩選 ( Filters ) 。在 PollAdmin 內(nèi)添加一行如下所示的代碼::

list_filter = ['pub_date']

這就增加了一個(gè) “篩選” 的側(cè)邊欄,讓人們通過 pub_date 字段的值來篩選 change list 顯示的內(nèi)容:

顯示篩選的類型取決于你需要篩選的字段類型。 因?yàn)?pub_date 是一個(gè) DateTimeField 的實(shí)例,Django 知道提供對應(yīng)的篩選選項(xiàng):”Any date,” “Today,” “Past 7 days,” “This month,” “This year.”

為了效果更好。讓我們來加上搜索功能::

search_fields = ['question']

在 chang list 頁的頂部增加了一個(gè)搜索框。當(dāng)有人輸入了搜索條件, Django 將搜索 question 字段。 雖然你可以使用任意數(shù)量的字段,如你希望的那樣 – 但是因?yàn)樗诤笈_用 LIKE 查詢,為了保持?jǐn)?shù)據(jù)庫的性能請合理使用。

最后,因?yàn)?Poll 對象有日期字段,根據(jù)日期來向下鉆取記錄將會很方便。 添加下面這一行代碼::

date_hierarchy = 'pub_date'

這會在 change list 頁的頂部增加了基于日期的分層導(dǎo)航功能。 在最頂層,顯示所有可用年份。然后可鉆取到月份,最終到天。

現(xiàn)在又是一個(gè)好時(shí)機(jī),請注意 change lists 頁面提供了分頁功能。默認(rèn)情況下每一頁顯示 100 條記錄。 Change-list 分頁,搜索框,篩選,日期分層和列標(biāo)題排序如你所原地在一起運(yùn)行了。

自定義管理界面的外觀

顯而易見,在每一個(gè)管理頁面頂部有 “Django administration” 是無語的。雖然它僅僅是個(gè)占位符。

不過使用 Django 的模板系統(tǒng)是很容易改變的。Django 管理網(wǎng)站有 Django 框架自身的功能,可以通過 Django 自身的模板系統(tǒng)來修改界面。

自定義你的 項(xiàng)目 模板

在你的項(xiàng)目目錄下創(chuàng)建一個(gè) templates 目錄。模板可以放在你的文件系統(tǒng)的任何地方,Diango 都能訪問。 (Django 能以任何用戶身份在你的服務(wù)器上運(yùn)行。) 然后,在你的項(xiàng)目中保存模板是一個(gè)好習(xí)慣。

默認(rèn)情況下,TEMPLATE_DIRS 值是空的。因此,讓我們添加一行代碼,來告訴 Django 我們的模板在哪里::

TEMPLATE_DIRS = (
    '/path/to/mysite/templates', # 將此處改為你的目錄。
)

現(xiàn)在從 Django 源代碼中自帶的默認(rèn) Django 管理模板的目錄 (django/contrib/admin/templates) 下復(fù)制 admin/base_site.html 模板到你正在使用的 TEMPLATE_DIRS 中任何目錄的子目錄 admin 下。例如:如果你的 TEMPLATE_DIRS 中包含 '/path/to/mysite/templates' 目錄, 如上所述,復(fù)制 django/contrib/admin/templates/admin/base_site.html 模板到 /path/to/mysite/templates/admin/base_site.html 。不要忘了是 admin 子目錄。

Django 的源代碼在哪里?

如果在你的文件系統(tǒng)中很難找到 Django 源代碼,可以運(yùn)行如下命令:

python -c "
import sys
sys.path = sys.path[1:]
import django
print(django.__path__)"

然后,只需要編輯該文件并將通用的 Djangot 文字替換為你認(rèn)為適合的屬于你自己的網(wǎng)站名。

該模板包含了大量的文字,比如 {% block branding %}{{ title }}{%{{ 標(biāo)記是 Django 模板語言的一部分。 當(dāng) Django 呈現(xiàn) admin/base_site.html 時(shí),根據(jù)模板語言生成最終的 HTML 頁面。 Don’t worry if you can’t make any sense of the template right now – 如果你現(xiàn)在不能理解模板的含義先不用擔(dān)心 – 我們將在教程 3 中深入探討 Django’ 的模板語言。

請注意 Django 默認(rèn)的管理網(wǎng)站中的任何模板都是可覆蓋的。 要覆蓋一個(gè)模板,只需要像剛才處理 base_site.html 一樣 – 從默認(rèn)的目錄下復(fù)制到你的自定義目錄下,并修改它。

自定義你的 應(yīng)用 模板

細(xì)心的讀者會問:如果 TEMPLATE_DIRS 默認(rèn)的情況下是空值, 那 Django 是如何找到默認(rèn)的管理網(wǎng)站的模板的? 答案就是在默認(rèn)情況下, Django 會自動在每一個(gè)應(yīng)用的包內(nèi)查找 templates/ 目錄,作為備用使用。 (不要忘記 django.contrib.admin 是一個(gè)應(yīng)用)。

我們的 poll 應(yīng)用不是很復(fù)雜并不需要自定義管理模板。但是如果它變得更復(fù)雜 而且為了一些功能需要修改 Django 的標(biāo)準(zhǔn)管理模板,修改應(yīng)用模板將是更 明智的選擇,而不是修改項(xiàng)目模板。通過這種方式,你可以在任何新項(xiàng)目包括 polls 應(yīng)用中自定義模板并且放心會找到需要的自定義的模板的。

有關(guān) Django 怎樣找到它的模板的更多信息,請參考 模板加載文檔 。

自定義管理網(wǎng)站的首頁

于此類似,你可能還想自定義 Django 管理網(wǎng)站的首頁。

默認(rèn)情況下,首頁會顯示在 INSTALLED_APPS 中所有注冊了管理功能的應(yīng)用, 并按字母排序。你可能想在頁面布局上做大修改??傊?,首頁可能是管理網(wǎng)站中最重要的頁面, 因此它應(yīng)該很容易使用。

你需要自定義的模板是 admin/index.html 。 (同先前處理 admin/base_site.html 一樣 – 從默認(rèn)目錄下復(fù)制到你自定義的模板目錄下。) 編輯這個(gè)文件,你將看到一個(gè)名為 app_list 的模板變量。這個(gè)變量包含了每一個(gè) 已安裝的 Django 應(yīng)用。你可以通過你認(rèn)為最好的方法硬編碼鏈接到特定對象的管理頁面,而不是使用默認(rèn)模板。 再次強(qiáng)調(diào),如果你不能理解模板語言的話不用擔(dān)心 – 我們將在教程 3 中詳細(xì)介紹。

當(dāng)你熟悉了管理網(wǎng)站的功能后,閱讀 教程 第3部分 開始開發(fā)公共 poll 界面。

譯者:Django 文檔協(xié)作翻譯小組,原文:Part 2: The admin site

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

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