第六章 Django站點管理

第六章 Django站點管理

對於某一類網站, 管理界面 是基礎設施中很是重要的一部分。 這是以網頁和有限的可信任管理者爲基礎的界面,它可讓你添加,編輯和刪除網站內容。 一些常見的例子: 你能夠用這個界面發佈博客,後臺的網站管理者用它來潤色讀者提交的內容,你的客戶用你給他們創建的界面工具更新新聞併發布在網站上,這些都是使用管理界面的例子。python

可是管理界面有一問題: 建立它太繁瑣。 當你開發對公衆的功能時,網頁開發是有趣的,可是建立管理界面一般是千篇一概的。 你必須認證用戶,顯示並管理表格,驗證輸入的有效性諸如此類。 這很繁瑣並且是重複勞動。程序員

Django 在對這些繁瑣和重複的工做進行了哪些改進? 它用不能再少的代碼爲你作了全部的一切。 Django 中建立管理界面已經不是問題。shell

這一章是關於 Django 的自動管理界面。 這個特性是這樣起做用的: 它讀取你模式中的元數據,而後提供給你一個強大並且可使用的界面,網站管理者能夠用它當即工做。數據庫

請注意咱們建議你讀這章,即便你不打算用admin。由於咱們將介紹一些概念,這些概念能夠應用到Django的全部方面,而不只僅是admindjango

django.contrib 包

Django自動管理工具是django.contrib的一部分。django.contrib是一套 龐大的功能集,它是Django基本代碼的組成部分,Django框架就是由衆多包含附加組件(add-on)的基本代碼構成的。 你能夠把django.contrib看做是可選的Python標準庫或廣泛模式的實際實現。 它們與Django捆綁在一塊兒,這樣你在開發中就不用「重複發明輪子」了。編程

管理工具是本書講述django.contrib的第一個部分。從技術層面上講,它被稱做 django.contrib.admin。django.contrib中其它可用的特性,如用戶鑑別系統 (django.contrib.auth)、支持匿名會話(django.contrib.sessioins)以及用戶評註系統 (django.contrib.comments)。這些,咱們將在第十六章詳細討論。在成爲一個Django專家之前,你將會知道更多 django.contrib的特性。 目前,你只須要知道Django自帶不少優秀的附加組件,它們都存在於django.contrib包裏。瀏覽器

激活管理界面

Django管理站點徹底是可選擇的,由於僅僅某些特殊類型的站點才須要這些功能。 這意味着你須要在你的項目中花費幾個步驟去激活它。服務器

第一步,對你的settings文件作以下這些改變:網絡

  1. 'django.contrib.admin'加入setting的INSTALLED_APPS配置中 (INSTALLED_APPS中的配置順序是沒有關係的, 可是咱們喜歡保持必定順序以方便人來閱讀)session

  2. 保證INSTALLED_APPS中包含'django.contrib.auth''django.contrib.contenttypes''django.contrib.sessions',Django的管理工具須要這3個包。 (若是你跟隨本文製做mysite項目的話,那麼請注意咱們在第五章的時候把這三項INSTALLED_APPS條目註釋了。如今,請把註釋取消。)

  3. 確保MIDDLEWARE_CLASSES 包含'django.middleware.common.CommonMiddleware' 、'django.contrib.sessions.middleware.SessionMiddleware' 和'django.contrib.auth.middleware.AuthenticationMiddleware' 。(再次提醒,若是有跟着作mysite的話,請把在第五章作的註釋取消。)

運行 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這個命令纔可用.)

第三,將admin訪問配置在URLconf(記住,在urls.py中). 默認狀況下,命令django-admin.py startproject生成的文件urls.py是將Django admin的路徑註釋掉的,你所要作的就是取消註釋。 請注意,如下內容是必須確保存在的:

# Include these import statements...
from django.contrib import admin
admin.autodiscover()

# And include this URLpattern...
urlpatterns = patterns('',
    # ...
    (r'^admin/', include(admin.site.urls)),
    # ...
)

當這一切都配置好後,如今你將發現Django管理工具能夠運行了。 啓動開發服務器(如前:`` python manage.py runserver`` ),而後在瀏覽器中訪問:http://127.0.0.1:8000/admin/

,使用管理工具。

管理界面的設計是針對非技術人員的,因此它應該是自我解釋的。 儘管如此,這裏簡單介紹一下它的基本特性。

你看到的第一件事是如圖6-1所示的登陸屏幕。

Django 登陸頁面的截圖。

圖 6-1. Django的登陸截圖

你要使用你原來設置的超級用戶的用戶名和密碼。 若是沒法登陸,請運行`` python manage.py createsuperuser`` ,確保你已經建立了一個超級用戶。

一旦登陸了,你將看到管理頁面。 這個頁面列出了管理工具中可編輯的全部數據類型。 如今,因爲咱們尚未建立任何模塊,因此這個列表只有寥寥數條類目: 它僅有兩個默認的管理-編輯模塊:用戶組(Groups)和用戶(Users)。

Django 主管理索引截圖。

圖 6-2。 Django admin的首頁

在Django管理頁面中,每一種數據類型都有一個* change list* 和* edit form* 。前者顯示數據庫中全部的可用對象;後者可以讓你添加、更改和刪除數據庫中的某條記錄。

其它語言

若是你的母語不是英語,而你不想用它來配置你的瀏覽器,你能夠作一個快速更改來觀察Django管理工 具是否被翻譯成你想要的語言。 僅需添加`` ‘django.middleware.locale.LocaleMiddleware’`` 到`` MIDDLEWARE_CLASSES`` 設置中,並確保它在’django.contrib.sessions.middleware.SessionMiddleware’* 以後* 。 (見上)

完成後,請刷新頁面。 若是你設置的語言可用,一系列的連接文字將被顯示成這種語言。這些文字包括頁面頂端的Change password和Log out,頁面中部的Groups和Users。 Django自帶了多種語言的翻譯。

關於Django更多的國際化特性,請參見第十九章。

點擊Uers行中的Change連接,引導用戶更改列表。

修改過的變動列表頁面截圖。

圖 6-3. 典型的改變列表視圖 (見上)

這個頁面顯示了數據庫中全部的用戶。你能夠將它看做是一個漂亮的網頁版查詢:`` SELECT * FROM auth_user;`` 若是你一直跟着做練習,而且只添加了一個用戶,你會在這個頁面中看到一個用戶。可是若是你添加了多個用戶,你會發現頁面中還有過濾器、排序和查詢框。 過濾器在右邊;排序功能可經過點擊列頭查看;查詢框在頁面頂部,它容許你經過用戶名查詢。

點擊其中一個用戶名,你會看見關於這個用戶的編輯窗口。

典型的編輯表格截圖。

圖 6-4. 典型的編輯表格 (見上)

這個頁面容許你修改用戶的屬性,如姓名和權限。 (若是要更改用戶密碼,你必須點擊密碼字段下的change password form,而不是直接更改字段值中的哈西碼。)另外須要注意的是,不一樣類型的字段會用不一樣的窗口控件顯示。例如,日期/時間型用日曆控件,布爾型用複選 框,字符型用簡單文本框顯示。

你能夠經過點擊編輯頁面下方的刪除按鈕來刪除一條記錄。 你會見到一個確認頁面。有時候,它會顯示有哪些關聯的對象將會一併被刪除。 (例如,若是你要刪除一個出版社,它下面全部的圖書也將被刪除。)

你能夠經過點擊管理主頁面中某個對象的Add來添加一條新記錄。 一個空白記錄的頁面將被打開,等待你填充。

你還能看到管理界面也控制着你輸入的有效性。 你能夠試試不填必需的欄目或者在時間欄裏填錯誤的時間,你會發現當你要保存時會出現錯誤信息,如圖6-5所示。

編輯表格顯示錯誤信息的截圖。

圖6-5. 編輯表格顯示錯誤信息 (見上)

當你編輯已有的對像時,你在窗口的右上角能夠看到一個歷史按鈕。 經過管理界面作的每個改變都留有記錄,你能夠按歷史鍵來檢查這個記錄(見圖6-6)。

Django 歷史頁面截圖。

圖6-6. Django 對像歷史頁面 (見上)

將你的Models加入到Admin管理中

有一個關鍵步驟咱們還沒作。 讓咱們將本身的模塊加入管理工具中,這樣咱們就可以經過這個漂亮的界面添加、修改和刪除數據庫中的對象了。 咱們將繼續第五章中的`` book`` 例子。在其中,咱們定義了三個模塊: Publisher 、 Author 和 Book 。

在`` books`` 目錄下(`` mysite/books`` ),建立一個文件:`` admin.py`` ,而後輸入如下代碼:

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)

這些代碼通知管理工具爲這些模塊逐一提供界面。

完成後,打開頁面 `` http://127.0.0.1:8000/admin/`` ,你會看到一個Books區域,其中包含Authors、Books和Publishers。  (你可能須要先中止,而後再啓動服務(`` runserver`` ),才能使其生效。)

如今你擁有一個功能完整的管理界面來管理這三個模塊了。 很簡單吧!

花點時間添加和修改記錄,以填充數據庫。 若是你跟着第五章的例子一塊兒建立Publisher對象的話(而且沒有刪除),你會在列表中看到那些記錄。

這裏須要提到的一個特性是,管理工具處理外鍵和多對多關係(這兩種關係能夠在`` Book`` 模塊中找到)的方法。 做爲提醒,這裏有個`` Book`` 模塊的例子:

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    def __unicode__(self):
        return self.title

在Add book頁面中(`` http://127.0.0.1:8000/admin/books/book/add/`` ),`` 外鍵`` publisher用一個選擇框顯示,`` 多對多`` 字段author用一個多選框顯示。 點擊兩個字段後面的綠色加號,可讓你添加相關的記錄。 舉個例子,若是你點擊Publisher後面的加號,你將會獲得一個彈出窗口來添加一個publisher。 當你在那個窗口中成功建立了一個publisher後,Add book表單會自動把它更新到字段上去 花巧.

Admin是如何工做的

在幕後,管理工具是如何工做的呢? 其實很簡單。

當服務啓動時,Django從`` url.py`` 引導URLconf,而後執行`` admin.autodiscover()`` 語句。 這個函數遍歷INSTALLED_APPS配置,而且尋找相關的 admin.py文件。 若是在指定的app目錄下找到admin.py,它就執行其中的代碼。

在`` books`` 應用程序目錄下的`` admin.py`` 文件中,每次調用`` admin.site.register()`` 都將那個模塊註冊到管理工具中。 管理工具只爲那些明確註冊了的模塊顯示一個編輯/修改的界面。

應用程序`` django.contrib.auth`` 包含自身的`` admin.py`` ,因此Users和Groups能在管理工具中自動顯示。 其它的django.contrib應用程序,如django.contrib.redirects,其它從網上下在的第三方Django應用程序同樣,都會自行添加到管理工具。

綜上所述,管理工具其實就是一個Django應用程序,包含本身的模塊、模板、視圖和URLpatterns。 你要像添加本身的視圖同樣,把它添加到URLconf裏面。 你能夠在Django基本代碼中的django/contrib/admin目錄下,檢查它的模板、視圖和URLpatterns,但你不要嘗試直接修改其中的任何代碼,由於裏面有不少地方可讓你自定義管理工具的工做方式。 (若是你確實想瀏覽Django管理工具的代碼,請謹記它在讀取關於模塊的元數據過程當中作了些不簡單的工做,所以最好花些時間閱讀和理解那些代碼。)

設置字段可選

在擺弄了一會以後,你或許會發現管理工具備個限制:編輯表單須要你填寫每個字段,然而在有些狀況下,你想要某些字段是可選的。 舉個例子,咱們想要Author模塊中的email字段成爲可選,即容許不填。 在現實世界中,你可能沒有爲每一個做者登記郵箱地址。

爲了指定email字段爲可選,你只要編輯Book模塊(回想第五章,它在mysite/books/models.py文件裏),在email字段上加上blank=True。代碼以下:

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(**blank=True** )

這些代碼告訴Django,做者的郵箱地址容許輸入一個空值。 全部字段都默認blank=False,這使得它們不容許輸入空值。

這裏會發生一些有趣的事情。 直到如今,除了__unicode__()方法,咱們的模塊充當數據庫中表定義的角色,即本質上是用Python的語法來寫CREATE TABLE語句。 在添加blank=True過程當中,咱們已經開始在簡單的定義數據表上擴展咱們的模塊了。 如今,咱們的模塊類開始成爲一個富含Author對象屬性和行爲的集合了。 email不但展示爲一個數據庫中的VARCHAR類型的字段,它仍是頁面中可選的字段,就像在管理工具中看到的那樣。

當你添加blank=True之後,刷新頁面Add author edit form (http://127.0.0.1:8000/admin/books/author/add/ ),將會發現Email的標籤再也不是粗體了。 這意味它不是一個必填字段。 如今你能夠添加一個做者而沒必要輸入郵箱地址,即便你爲這個字段提交了一個空值,也再不會獲得那刺眼的紅色信息「This field is required」。

設置日期型和數字型字段可選

雖然blank=True一樣適用於日期型和數字型字段,可是這裏須要詳細講解一些背景知識。

SQL有指定空值的獨特方式,它把空值叫作NULL。NULL能夠表示爲未知的、非法的、或其它程序指定的含義。

在SQL中, NULL的值不一樣於空字符串,就像Python中None不一樣於空字符串("")同樣。這意味着某個字符型字段(如VARCHAR)的值不可能同時包含NULL和空字符串。

這會引發沒必要要的歧義或疑惑。 爲何這條記錄有個NULL,而那條記錄卻有個空字符串? 它們之間有區別,仍是數據輸入不一致? 還有: 我怎樣才能獲得所有擁有空值的記錄,應該按NULL和空字符串查找麼?仍是僅按字符串查找?

爲了消除歧義,Django生成CREATE TABLE語句自動爲每一個字段顯式加上NOT NULL。 這裏有個第五章中生成Author模塊的例子:

CREATE TABLE "books_author" (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(40) NOT NULL,
    "email" varchar(75) NOT NULL
)
;

在大多數狀況下,這種默認的行爲對你的應用程序來講是最佳的,由於它可使你再也不因數據一致性而頭痛。 並且它能夠和Django的其它部分工做得很好。如在管理工具中,若是你留空一個字符型字段,它會爲此插入一個空字符串(而* 不是*NULL)。

可是,其它數據類型有例外:日期型、時間型和數字型字段不接受空字符串。 若是你嘗試將一個空字符串插入日期型或整數型字段,你可能會獲得數據庫返回的錯誤,這取決於那個數據庫的類型。 (PostgreSQL比較嚴禁,會拋出一個異常;MySQL可能會也可能不會接受,這取決於你使用的版本和運氣了。)在這種狀況下,NULL是惟一指定空值的方法。 在Django模塊中,你能夠經過添加null=True來指定一個字段容許爲NULL

所以,這提及來有點複雜: 若是你想容許一個日期型(DateFieldTimeFieldDateTimeField)或數字型(IntegerFieldDecimalFieldFloatField)字段爲空,你須要使用null=True * 和* blank=True

爲了舉例說明,讓咱們把Book模塊修改爲容許 publication_date爲空。修改後的代碼以下:

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField(**blank=True, null=True** )

添加null=True比添加blank=True複雜。由於null=True改變了數據的語義,即改變了CREATE TABLE語句,把publication_date字段上的NOT NULL刪除了。 要完成這些改動,咱們還須要更新數據庫。

出於某種緣由,Django不會嘗試自動更新數據庫結構。因此你必須執行ALTER TABLE語句將模塊的改動更新至數據庫。 像先前那樣,你可使用manage.py dbshell進入數據庫服務環境。 如下是在這個特殊狀況下如何刪除NOT NULL:

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

(注意:如下SQL語法是PostgreSQL特有的。)

咱們將在第十章詳細講述數據庫結構更改。

如今讓咱們回到管理工具,添加book的編輯頁面容許輸入一個空的publication date。

自定義字段標籤

在編輯頁面中,每一個字段的標籤都是從模塊的字段名稱生成的。 規則很簡單: 用空格替換下劃線;首字母大寫。例如:Book模塊中publication_date的標籤是Publication date。

然而,字段名稱並不老是貼切的。有些狀況下,你可能想自定義一個標籤。 你只需在模塊中指定verbose_name

舉個例子,說明如何將Author.email的標籤改成e-mail,中間有個橫線。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, **verbose_name='e-mail'** )

修改後重啓服務器,你會在author編輯頁面中看到這個新標籤。

請注意,你沒必要把verbose_name的首字母大寫,除非是連續大寫(如:"USA state")。Django會自動適時將首字母大寫,而且在其它不須要大寫的地方使用verbose_name的精確值。

最後還需注意的是,爲了使語法簡潔,你能夠把它看成固定位置的參數傳遞。 這個例子與上面那個的效果相同。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(**'e-mail',**  blank=True)

但這不適用於ManyToManyField 和ForeignKey字段,由於它們第一個參數必須是模塊類。 那種情形,必須顯式使用verbose_name這個參數名稱。

自定義ModelAdmi類

迄今爲止,咱們作的blank=Truenull=Trueverbose_name修改實際上是模塊級別,而不是管理級別的。 也就是說,這些修改實質上是構成模塊的一部分,而且正好被管理工具使用,而不是專門針對管理工具的。

除了這些,Django還提供了大量選項讓你針對特別的模塊自定義管理工具。 這些選項都在ModelAdmin classes裏面,這些類包含了管理工具中針對特別模塊的配置。

自定義列表

讓咱們更深一步:自定義Author模塊的列表中的顯示字段。 列表默認地顯示查詢結果中對象的__unicode__()。 在第五章中,咱們定義Author對象的__unicode__()方法,用以同時顯示做者的姓和名。

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(blank=True, verbose_name='e-mail')

    **def __unicode__(self):**
        **return u'%s %s' % (self.first_name, self.last_name)**

結果正如圖6-7所示,列表中顯示的是每一個做者的姓名。

Screenshot of the author change list page.

圖 6-7. 做者列表

咱們能夠在這基礎上改進,添加其它字段,從而改變列表的顯示。 這個頁面應該提供便利,好比說:在這個列表中能夠看到做者的郵箱地址。若是能按照姓氏或名字來排序,那就更好了。

爲了達到這個目的,咱們將爲Author模塊定義一個ModelAdmin類。 這個類是自定義管理工具的關鍵,其中最基本的一件事情是容許你指定列表中的字段。 打開admin.py並修改:

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

**class AuthorAdmin(admin.ModelAdmin):**
    **list_display = ('first_name', 'last_name', 'email')**

admin.site.register(Publisher)
**admin.site.register(Author, AuthorAdmin)**
admin.site.register(Book)

解釋一下代碼:

咱們新建了一個類AuthorAdmin,它是從django.contrib.admin.ModelAdmin派生出來的子類,保存着一個類的自定義配置,以供管理工具使用。 咱們只自定義了一項:list_display, 它是一個字段名稱的元組,用於列表顯示。 固然,這些字段名稱必須是模塊中有的。

咱們修改了admin.site.register()調用,在Author後面添加了AuthorAdmin。你能夠這樣理解: 用AuthorAdmin選項註冊Author模塊。

admin.site.register()函數接受一個ModelAdmin子類做爲第二個參數。 若是你忽略第二個參數,Django將使用默認的選項。PublisherBook的註冊就屬於這種狀況。

弄好了這個東東,再刷新author列表頁面,你會看到列表中有三列:姓氏、名字和郵箱地址。 另外,點擊每一個列的列頭能夠對那列進行排序。 (參見圖 6-8)

Screenshot of the author change list page after list_display.

圖 6-8. 修改後的author列表頁面

接下來,讓咱們添加一個快速查詢欄。 向AuthorAdmin追加search_fields,如:

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email')
    **search_fields = ('first_name', 'last_name')**

刷新瀏覽器,你會在頁面頂端看到一個查詢欄。 (見圖6-9.)咱們剛纔所做的修改列表頁面,添加了一個根據姓名查詢的查詢框。 正如用戶所但願的那樣,它是大小寫敏感,而且對兩個字段檢索的查詢框。若是查詢"bar",那麼名字中含有Barney和姓氏中含有Hobarson的做者記錄將被檢索出來。

Screenshot of the author change list page after search_fields.

圖 6-9. 含search_fields的author列表頁面

接下來,讓咱們爲Book列表頁添加一些過濾器。

from django.contrib import admin
from mysite.books.models import Publisher, Author, Book

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'email')
    search_fields = ('first_name', 'last_name')

**class BookAdmin(admin.ModelAdmin):**
    **list_display = ('title', 'publisher', 'publication_date')**
    **list_filter = ('publication_date',)**

admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
**admin.site.register(Book, BookAdmin)**

因爲咱們要處理一系列選項,所以咱們建立了一個單獨的ModelAdmin類:BookAdmin。首先,咱們定義一個list_display,以使得頁面好看些。 而後,咱們用list_filter這個字段元組建立過濾器,它位於列表頁面的右邊。 Django爲日期型字段提供了快捷過濾方式,它包含:今天、過往七天、當月和今年。這些是開發人員常常用到的。 圖 6-10顯示了修改後的頁面。

Screenshot of the book change list page after list_filter.

圖 6-10. 含過濾器的book列表頁面

`` 過濾器`` 一樣適用於其它類型的字段,而不單是`` 日期型`` (請在`` 布爾型`` 和`` 外鍵`` 字段上試試)。當有兩個以上值時,過濾器就會顯示。

另一種過濾日期的方式是使用date_hierarchy選項,如:

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    **date_hierarchy = 'publication_date'**

修改好後,頁面中的列表頂端會有一個逐層深刻的導航條,效果如圖 6-11. 它從可用的年份開始,而後逐層細分到月乃至日。

Screenshot of the book change list page after date_hierarchy.

圖 6-11. 含date_hierarchy的book列表頁面

請注意,date_hierarchy接受的是* 字符串* ,而不是元組。由於只能對一個日期型字段進行層次劃分。

最後,讓咱們改變默認的排序方式,按publication date降序排列。 列表頁面默認按照模塊class Meta(詳見第五章)中的ordering所指的列排序。但目前沒有指定ordering值,因此當前排序是沒有定義的。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    **ordering = ('-publication_date',)**

這個ordering選項基本像模塊中class Metaordering那樣工做,除了它只用列表中的第一個字段名。 若是要實現降序,僅需在傳入的列表或元組的字段前加上一個減號(-)。

刷新book列表頁面觀看實際效果。 注意Publication date列頭如今有一個小箭頭顯示排序。 (見圖 6-12.)

Screenshot of the book change list page after ordering.

圖 6-12 含排序的book列表頁面

咱們已經學習了主要的選項。 經過使用它們,你能夠僅需幾行代碼就能建立一個功能強大、隨時上線的數據編輯界面。

自定義編輯表單

正如自定義列表那樣,編輯表單多方面也能自定義。

首先,咱們先自定義字段順序。 默認地,表單中的字段順序是與模塊中定義是一致的。 咱們能夠經過使用ModelAdmin子類中的fields選項來改變它:

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **fields = ('title', 'authors', 'publisher', 'publication_date')**

完成以後,編輯表單將按照指定的順序顯示各字段。 它看起來天然多了——做者排在書名以後。 字段順序固然是與數據條目錄入順序有關, 每一個表單都不同。

經過fields這個選項,你能夠排除一些不想被其餘人編輯的fields 只要不選上不想被編輯的field(s)便可。 當你的admi用戶只是被信任能夠更改你的某一部分數據時,或者,你的數據被一些外部的程序自動處理而改變了了,你就能夠用這個功能。 例如,在book數據庫中,咱們能夠隱藏publication_date,以防止它被編輯。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **fields = ('title', 'authors', 'publisher')**

這樣,在編輯頁面就沒法對publication date進行改動。 若是你是一個編輯,不但願做者推遲出版日期的話,這個功能就頗有用。 (固然,這純粹是一個假設的例子。)

當一個用戶用這個不包含完整信息的表單添加一本新書時,Django會簡單地將publication_date設置爲None,以確保這個字段知足null=True的條件。

另外一個經常使用的編輯頁面自定義是針對多對多字段的。 真如咱們在book編輯頁面看到的那樣,`` 多對多字段`` 被展示成多選框。雖然多選框在邏輯上是最適合的HTML控件,但它卻不那麼好用。 若是你想選擇多項,你必須還要按下Ctrl鍵(蘋果機是command鍵)。 雖然管理工具所以添加了註釋(help_text),可是當它有幾百個選項時,它依然顯得笨拙。

更好的辦法是使用filter_horizontal。讓咱們把它添加到BookAdmin中,而後看看它的效果。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    **filter_horizontal = ('authors',)**

(若是你一着跟着作練習,請注意移除fields選項,以使得編輯頁面包含全部字段。)

刷新book編輯頁面,你會看到Author區中有一個精巧的JavaScript過濾器,它容許你檢索選項,而後將選中的authors從Available框移到Chosen框,還能夠移回來。

Screenshot of the book edit form after adding filter_horizontal.

圖 6-13. 含filter_horizontal的book編輯頁面

咱們強烈建議針對那些擁有十個以上選項的`` 多對多字段`` 使用filter_horizontal。 這比多選框好用多了。 你能夠在多個字段上使用filter_horizontal,只需在這個元組中指定每一個字段的名字。

ModelAdmin類還支持filter_vertical選項。 它像filter_horizontal那樣工做,除了控件都是垂直排列,而不是水平排列的。 至於使用哪一個,只是我的喜愛問題。

filter_horizontalfilter_vertical選項只能用在多對多字段 上, 而不能用於 ForeignKey字 段。 默認地,管理工具使用`` 下拉框`` 來展示`` 外鍵`` 字段。可是,正如`` 多對多字段`` 那樣,有時候你不想忍受因裝載並顯示這些選項而產生的大量開銷。 例如,咱們的book數據庫膨脹到擁有數千條publishers的記錄,以至於book的添加頁面裝載時間較久,由於它必須把每個publishe都 裝載並顯示在`` 下拉框`` 中。

解決這個問題的辦法是使用`` raw_id_fields`` 選項。它是一個包含外鍵字段名稱的元組,它包含的字段將被展示成`` 文本框`` ,而再也不是`` 下拉框`` 。見圖 6-14。

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'publisher', 'publication_date')
    list_filter = ('publication_date',)
    date_hierarchy = 'publication_date'
    ordering = ('-publication_date',)
    filter_horizontal = ('authors',)
    **raw_id_fields = ('publisher',)**

Screenshot of edit form after raw_id_fields.

圖 6-14. 含raw_id_fields的book編輯頁面

在這個輸入框中,你輸入什麼呢? publisher的數據庫ID號。 考慮到人們一般不會記住這些數據庫ID,管理工具提供了一個放大鏡圖標方便你輸入。點擊那個圖標將會彈出一個窗口,在那裏你能夠選擇想要添加的publishe。

用戶、用戶組和權限

由於你是用超級用戶登陸的,你能夠建立,編輯和刪除任何對像。 然而,不一樣的環境要求有不一樣的權限,系統不容許全部人都是超級用戶。 管理工具備一個用戶權限系統,經過它你能夠根據用戶的須要來指定他們的權限,從而達到部分訪問系統的目的。

用戶賬號應該是通用的、獨立於管理界面之外仍可使用。但咱們如今把它看做是管理界面的一部分。 在第十四章,咱們將講述如何把用戶賬號與你的網站(不只僅是管理工具)集成在一塊兒。

你經過管理界面編輯用戶及其許可就像你編輯別的對象同樣。 咱們在本章的前面,瀏覽用戶和用戶組區域的時候已經見過這些了。 如你所想,用戶對象有標準的用戶名、密碼、郵箱地址和真實姓名,同時它還有關於使用管理界面的權限定義。 首先,這有一組三個布爾型標記:

  • 活動標誌,它用來控制用戶是否已經激活。 若是一個用戶賬號的這個標記是關閉狀態,而用戶又嘗試用它登陸時,即便密碼正確,他也沒法登陸系統。

  • 成員標誌,它用來控制這個用戶是否能夠登陸管理界面(即:這個用戶是否是大家組織裏的成員) 因爲用戶系統能夠被用於控制公衆頁面(即:非管理頁面)的訪問權限(詳見第十四章),這個標誌可用來區分公衆用戶和管理用戶。

  • 超級用戶標誌,它賦予用戶在管理界面中添加、修改和刪除任何項目的權限。 若是一個用戶賬號有這個標誌,那麼全部權限設置(即便沒有)都會被忽略。

普通的活躍,非超級用戶的管理用戶能夠根據一套設定好的許可進入。 管理界面中每種可編輯的對象(如:books、authors、publishers)都有三種權限: 建立 許可, 編輯 許可和 刪除 許可。 給一個用戶受權許可也就代表該用戶能夠進行許可描述的操做。

當你建立一個用戶時,它沒有任何權限,該有什麼權限是由你決定的。 例如,你能夠給一個用戶添加和修改publishers的權限,而不給他刪除的權限。 請注意,這些權限是定義在模塊級別上,而不是對象級別上的。據個例子,你可讓小強修改任何圖書,可是不能讓他僅修改由機械工業出版社出版的圖書。 後面這種基於對象級別的權限設置比較複雜,而且超出了本書的覆蓋範圍,但你能夠在Django documentation中尋找答案。

註釋

權限管理系統也控制編輯用戶和權限。 若是你給某人編輯用戶的權限,他能夠編輯本身的權限,這種能力可能不是你但願的。 賦予一個用戶修改用戶的權限,本質上說就是把他變成一個超級用戶。

你也能夠給組中分配用戶。 一個  簡化了給組中全部成員應用一套許可的動做。 組在給大量用戶特定權限的時候頗有用。

什麼時候、爲何使用管理界面?什麼時候又不使用呢?

通過這一章的學習,你應該對Django管理工具備所認識。 可是咱們須要代表一個觀點:* 何時* 、* 爲何* 用,以及何時又* 不* 用。

Django的管理界面對非技術用戶要輸入他們的數據時特別有用;事實上這個特性就是專門爲這個 實現的。 在Django最開始開發的新聞報道的行業應用中,有一個典型的在線自來水的水質專題報道 應用,它的實現流程是這樣的:

  • 負責這個報道的記者和要處理數據的開發者碰頭,提供一些數據給開發者。

  • 開發者圍繞這些數據設計模型而後配置一個管理界面給記者。

  • 記者檢查管理界面,儘早指出缺乏或多餘的字段。 開發者來回地修改模塊。

  • 當模塊承認後,記者就開始用管理界面輸入數據。 同時,程序員能夠專一於開發公衆訪問視圖和模板(有趣的部分)。

換句話說,Django的管理界面爲內容輸入人員和編程人員都提供了便利的工具。

固然,除了數據輸入方面,咱們發現管理界面在下面這些情景中也是頗有用的:

    • 檢查模塊* :當你定義好了若干個模塊,在管理頁面中把他們調出來而後輸入一些虛假的數據,這是至關有用的。 有時候,它能顯示數據建模的錯誤或者模塊中其它問題。

    • 管理既得數據* :若是你的應用程序依賴外部數據(來自用戶輸入或網絡爬蟲),管理界面提供了一個便捷的途徑,讓你檢查和編輯那些數據。 你能夠把它看做是一個功能不那麼強大,可是很方便的數據庫命令行工具。

    • 臨時的數據管理程序* :你能夠用管理工具創建本身的輕量級數據管理程序,好比說開銷記錄。 若是你正在根據本身的,而不是公衆的須要開發些什麼,那麼管理界面能夠帶給你很大的幫助。 從這個意義上講,你能夠把它看做是一個加強的關係型電子表格。

最後一點要澄清的是: 管理界面不是終結者。 過往許多年間,咱們看到它被拆分、修改爲若干個功能模塊,而這些功能不是它所支持的。 它不該成爲一個* 公衆* 數據訪問接口,也不該容許對你的數據進行復雜的排序和查詢。 正如本章開頭所說,它僅提供給可信任的管理員。 請記住這一點,它是有效使用管理界面的鑰匙。

相關文章
相關標籤/搜索