之前的幾篇記錄了模板視圖、模型等頁面展示的相關內容,這篇主要寫一下后台admin管理界面的內容。
激活管理界面
Django管理站點完全是可選擇的,之前我們是把這些功能給屏蔽掉了。記得上篇中Django模型模型安裝小結中,我們把settings.py中的部分內容屏蔽了,並添加了一個app,如下
1 INSTALLED_APPS = ( 2 ## 'django.contrib.admin', 3 ## 'django.contrib.auth', 4 ## 'django.contrib.contenttypes', 5 ## 'django.contrib.sessions', 6 ## 'django.contrib.messages', 7 ## 'django.contrib.staticfiles', 8 'mysite.books', 9 ) 10 11 MIDDLEWARE_CLASSES = ( 12 ## 'django.contrib.sessions.middleware.SessionMiddleware', 13 ## 'django.middleware.common.CommonMiddleware', 14 ## 'django.middleware.csrf.CsrfViewMiddleware', 15 ## 'django.contrib.auth.middleware.AuthenticationMiddleware', 16 ## 'django.contrib.messages.middleware.MessageMiddleware', 17 ## 'django.middleware.clickjacking.XFrameOptionsMiddleware', 18 )
django.contrib.admin等這些就是支持后台admin管理界面的app,我們將上邊這些注釋全部去掉,即可增加對后台管理界面的支持。
運行 python manage.py syncdb 。這一步將生成管理界面使用的額外數據庫表。 當你把'django.contrib.auth'加進INSTALLED_APPS后,第一次運行syncdb命令時, 系統會請你創建一個超級用戶。 如果你不這么作,你需要運行python manage.py createsuperuser來另外創建一個admin的用戶帳號,否則你將不能登入admin (提醒一句: 只有當INSTALLED_APPS包含'django.contrib.auth'時,python manage.py createsuperuser這個命令才可用.)
到這里,我們就把后台管理基本配置好了。但是想想,我們還差什么沒做?
時刻記得,去urls.py進行配置哦,下圖是新建的project初始時候的URLConf,在Django建立helloworld自定義頁面里我們刪除掉的內容
1 from django.conf.urls import patterns, include, url 2 3 from django.contrib import admin 4 5 admin.autodiscover() 6 7 urlpatterns = patterns('', 8 # Examples: 9 # url(r'^$', 'testsite.views.home', name='home'), 10 # url(r'^blog/', include('blog.urls')), 11 12 url(r'^admin/', include(admin.site.urls)), 13 14 )
現在,我們要訪問admin了,添加回來這幾句吧
from django.contrib import admin admin.autodiscover()
url(r'^admin/', include(admin.site.urls)),
好,我們運行起來看看吧。效果如下:
輸入之前你添加的管理員賬戶和密碼,登陸網站后台看看吧
如果你的母語不是英語,你可以做一個快速更改來觀察Django管理工具是否被翻譯成你想要的語言。 僅需添加 ‘django.middleware.locale.LocaleMiddleware’ 到 MIDDLEWARE_CLASSES 設置中,並確保它在’django.contrib.sessions.middleware.SessionMiddleware’后邊(其實先后是沒關系的)。如下我放在了第一個位置。
1 MIDDLEWARE_CLASSES = ( 2 'django.middleware.locale.LocaleMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 )
刷新一個剛才的頁面,看看效果。
具體的使用,無非就是增刪改查了,自己去點吧。
將自定義的Models加入到Admin管理中
上一篇Django模型-數據庫操作,我們定義了三個模塊:Publisher 、 Author 和 Book 。 讓我們將自己的模塊加入管理工具中,這樣我們就能夠通過這個后台管理界面添加、修改和刪除數據庫中的對象了。
還記得新建的books app初始化的幾個文件嗎?
打開admin.py,添加內容如下
1 from django.contrib import admin 2 3 # Register your models here. 4 from mysite.books.models import Publisher, Author, Book 5 6 admin.site.register(Publisher) 7 admin.site.register(Author) 8 admin.site.register(Book)
這些代碼通知管理工具為這些模塊逐一提供界面。你可能需要先停止,然后再啟動服務(runserver),才能使其生效。

Admin是如何工作的
當服務啟動時,Django從urls.py引導URLconf,然后執行admin.autodiscover()語句。 這個函數遍歷INSTALLED_APPS配置,並且尋找相關的 admin.py文件。 如果在指定的app目錄下找到admin.py,它就執行其中的代碼。
在books應用程序目錄下的admin.py文件中,每次調用admin.site.register()都將那個模塊注冊到管理工具中。 管理工具只為那些明確注冊了的模塊顯示一個編輯/修改的界面。
應用程序django.contrib.auth包含自身的admin.py,所以Users和Groups能在管理工具中自動顯示。
字段設置
我們嘗試添加一個作者信息,發現一些現象,每個字段都是必填項,Email也有專門的格式驗證。如果我們不想要這些限制,該怎么做呢?
修改我們的models.py如下
1 class Author(models.Model): 2 first_name = models.CharField(max_length=30) 3 last_name = models.CharField(max_length=40) 4 email = models.EmailField(blank=True) 5 6 def __unicode__(self): 7 return u'%s %s' % (self.first_name,self.last_name)
標紅部分是新添加的屬性,這些代碼告訴Django,作者的郵箱地址允許輸入一個空值。
所有字段都默認blank=False,這使得它們不允許輸入空值。
刷新頁面,將會發現Email的標簽不再是粗體,這意味它不是一個必填字段。
針對日期和數字的設置
Django生成CREATE TABLE語句自動為每個字段顯式加上NOT NULL,在大多數情況下,這種默認的行為對你的應用程序來說是最佳的(消除NULL和空字符串的數據不一致)。
但是,其它數據類型有例外:日期型、時間型和數字型字段不接受空字符串。 如果你嘗試將一個空字符串插入日期型或整數型字段,你可能會得到數據庫返回的錯誤,這取決於那個數據庫的類型。 (PostgreSQL比較嚴禁,會拋出一個異常;MySQL可能會也可能不會接受,這取決於你使用的版本和運氣了。)在這種情況下,NULL是唯一指定空值的方法。 在Django模塊中,你可以通過添加null=True來指定一個字段允許為NULL。
如果你想允許一個日期型(DateField、TimeField、DateTimeField)或數字型(IntegerField、DecimalField、FloatField)字段為空,你需要使用null=True 和 blank=True。
添加null=True比添加blank=True復雜。因為null=True改變了數據的語義,即改變了CREATE TABLE語句,把publication_date字段上的NOT NULL刪除了。 要完成這些改動,我們還需要更新數據庫。然而Django不會嘗試自動更新數據庫結構,所以你必須執行ALTER TABLE語句將模塊的改動更新至數據庫。
使用manage.py dbshell進入數據庫服務環境,執行命令
ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;
現在回到管理工具,添加book的編輯頁面就允許輸入一個空的publication date。


自定義字段標簽
在編輯頁面中,每個字段的標簽都是從模塊的字段名稱生成的。規則很簡答:用空格替換下划線;首字母大寫。比如上邊新增作者的那個截圖:first_name變成了First name。
有些情況下,我們想展示自定的標簽名。為做到這個,我們只需要在models的模塊定義中指定verbose_name即可。
比如我們要將Author.email的標簽改成e-mail,中間有個橫線,可以這樣做
1 class Author(models.Model): 2 first_name = models.CharField(max_length=30) 3 last_name = models.CharField(max_length=40) 4 email = models.EmailField(blank=True,verbose_name='e-mail')
重新啟動服務,刷新頁面,效果如下
1 class Author(models.Model): 2 first_name = models.CharField(max_length=30) 3 last_name = models.CharField(max_length=40) 4 email = models.EmailField('e-mail', blank=True)
但這不適用於ManyToManyField 和ForeignKey字段,因為它們第一個參數必須是模塊類。 那種情形,必須顯式使用verbose_name這個參數名稱。
自定義ModelAdmin類
自定義列表
1 class Author(models.Model): 2 first_name = models.CharField(max_length=30) 3 last_name = models.CharField(max_length=40) 4 email = models.EmailField(blank=True,verbose_name='e-mail') 5 6 def __unicode__(self): 7 return u'%s %s' % (self.first_name,self.last_name)

我們可以在這基礎上改進,添加其它字段,從而改變列表的顯示。 這個頁面應該提供便利,比如說:在這個列表中可以看到作者的郵箱地址。如果能按照姓氏或名字來排序,那就更好了。
為了達到這個目的,我們將為Author模塊定義一個ModelAdmin類。 這個類是自定義管理工具的關鍵,其中最基本的一件事情是允許你指定列表中的字段。 打開admin.py並修改:
1 from django.contrib import admin 2 from models import * 3 4 # Register your models here. 5 6 class AuthorAdmin(admin.ModelAdmin): 7 list_display = ('first_name', 'last_name', 'email') 8 9 admin.site.register(Publisher) 10 admin.site.register(Author,AuthorAdmin) 11 admin.site.register(Book)
我們新建了一個類AuthorAdmin,它是從django.contrib.admin.ModelAdmin派生出來的子類,保存着一個類的自定義配置,以供管理工具使用。 我們只自定義了一項:list_display, 它是一個字段名稱的元組,用於列表顯示。 當然,這些字段名稱必須是模塊中有的。

1 class AuthorAdmin(admin.ModelAdmin): 2 list_display = ('first_name', 'last_name', 'email') 3 search_fields = ('first_name', 'last_name')
刷新頁面,效果如下

1 from django.contrib import admin 2 from models import * 3 4 # Register your models here. 5 6 class AuthorAdmin(admin.ModelAdmin): 7 list_display = ('first_name', 'last_name', 'email') 8 search_fields = ('first_name', 'last_name') 9 10 class BookAdmin(admin.ModelAdmin): 11 list_display=('title','publisher','publication_date') 12 list_filter=('publication_date',) 13 14 admin.site.register(Publisher) 15 admin.site.register(Author,AuthorAdmin) 16 admin.site.register(Book,BookAdmin)
刷新效果如下:
1 class BookAdmin(admin.ModelAdmin): 2 list_display=('title','publisher','publication_date') 3 list_filter=('publication_date',) 4 date_hierarchy = 'publication_date'
修改好后,頁面中的列表頂端會有一個逐層深入的導航條,效果如圖 6-11. 它從可用的年份開始,然后逐層細分到月乃至日。
查看結果如下
1 class BookAdmin(admin.ModelAdmin): 2 list_display=('title','publisher','publication_date') 3 list_filter=('publication_date',) 4 date_hierarchy = 'publication_date' 5 ordering = ('-publication_date',)
這個ordering選項基本像模塊中class Meta的ordering那樣工作。效果是Publication date列頭現在有一個小箭頭顯示排序。
自定義編輯表單
首先,我們先自定義字段順序。 默認地,表單中的字段順序是與模塊中定義是一致的。 我們可以通過使用ModelAdmin子類中的fields選項來改變它:
1 class BookAdmin(admin.ModelAdmin): 2 list_display=('title','publisher','publication_date') 3 list_filter=('publication_date',) 4 date_hierarchy = 'publication_date' 5 ordering = ('-publication_date',) 6 fields = ('authors', 'title', 'publisher')
順序是我們自定義的,可編輯的字段也是我們可選擇的。效果如下:
此時新增記錄,Django會簡單地將publication_date設置為None,以確保這個字段滿足null=True的條件。
因為之前我說的,本地的Python manage.py dbshell 失敗,導致我無法修改數據庫結構,
publication_date = models.DateField(blank=True,null=True)
這段代碼是失效的,所以我在這里提交代碼會出錯,如下:
如果你本地的命令沒問題,並且根據之前的說明修改了對應數據庫字段可空(NULL和空字符串),則不會出錯。
另一個常用的編輯頁面自定義是針對多對多字段的。 真如我們在book編輯頁面看到的那樣, '多對多字段' 被展現成多選框。雖然多選框在邏輯上是最適合的HTML控件,但它卻不那么好用。 如果你想選擇多項,你必須還要按下Ctrl鍵。 雖然管理工具添加了注釋(help_text),但是當它有幾百個選項時,它依然顯得笨拙。
更好的辦法是使用filter_horizontal。讓我們把它添加到BookAdmin中,然后看看它的效果。
1 class BookAdmin(admin.ModelAdmin): 2 list_display=('title','publisher','publication_date') 3 list_filter=('publication_date',) 4 date_hierarchy = 'publication_date' 5 ordering = ('-publication_date',) 6 #fields = ('authors', 'title', 'publisher') 7 filter_horizontal = ('authors',)
效果如下
ModelAdmin類還支持filter_vertical選項。 它像filter_horizontal那樣工作,除了控件都是垂直排列,而不是水平排列的。
filter_horizontal和filter_vertical選項只能用在多對多字段 上, 而不能用於 ForeignKey字段。 默認地,管理工具使用'下拉框' 來展現 外鍵 字段。下拉框選擇就會將所有值加載到下拉列表,選中某個或許需要拖滾動條好久才能找到。
Django提供了raw_id_fields 選項,它是一個包含外鍵字段名稱的元組,它包含的字段將被展現成’ 文本框‘和檢索按鈕的形式。
1 class BookAdmin(admin.ModelAdmin): 2 list_display=('title','publisher','publication_date') 3 list_filter=('publication_date',) 4 date_hierarchy = 'publication_date' 5 ordering = ('-publication_date',) 6 #fields = ('authors', 'title', 'publisher') 7 filter_vertical = ('authors',) 8 raw_id_fields = ('publisher',)
這個文框內可輸入的值是publisher的id,通過檢索彈框選擇即可。
小結
這篇篇幅較長,內容不少。還有一部分關於權限的東西,這里不多說了,后台里多點點就能理解。