Django 教程 第 4 部分:Django 管理站點

現在,我們已經為LocalLibrary網站建立了模型,我們將使用Django Admin站點新增一些“真實”的書籍資料。首先,我們將向您展示如何將模型註冊到admin站點,然後我們將向您展示如何登入並建立一些資料。在文章的最後,我們將展示一些可以進一步改進Admin站點展示的方法。

先決條件 首先完成:Django教程第3部分:使用模型
目標 瞭解Django admin站點的優點和侷限性,並使用它為我們的模型建立一些記錄。

概述

Django admin應用程式可以使用您的模型自動構建一個站點區域,您可以使用它來建立、檢視、更新和刪除記錄。這可以在開發過程中為您節省大量時間,使您能夠輕鬆地測試您的模型,並瞭解您是否擁有正確的資料。admin應用程式還可以用於管理生產環境中的資料,具體取決於網站型別。Django專案建議將其僅用於內部資料管理(即僅供管理員或您組織內部人員使用),因為以模型為中心的做法並不一定是所有使用者的最佳介面,並且會公開大量關於模型的不必要細節。

將admin應用程式包含到您的網站中所需的所有配置是在您建立骨架專案時自動完成的(有關所需實際依賴項的資訊,請參閱此處的Django文件)。因此,您必須做的就是將您的模型註冊到admin應用程式。在本文的最後,我們將簡要演示如何進一步配置admin區域以更好地顯示我們的模型資料。

註冊模型後,我們將展示如何建立一個新的“超級使用者”,登入站點並建立一些書籍、作者、書籍例項和流派。這些對於我們在下一個教程中開始建立的檢視和模板進行測試將很有用。

註冊模型

首先,開啟目錄應用程式中的admin.py/django-locallibrary-tutorial/catalog/admin.py)。它目前看起來像這樣——請注意它已經匯入了django.contrib.admin

python
from django.contrib import admin

# Register your models here.

透過將以下文字複製到檔案底部來註冊模型。此程式碼匯入模型,然後呼叫admin.site.register來註冊每個模型。

python
from .models import Author, Genre, Book, BookInstance, Language

admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Genre)
admin.site.register(BookInstance)
admin.site.register(Language)

注意:上面的行假設您接受了建立模型來表示書籍的自然語言的挑戰(請參閱模型教程文章)!

這是將模型或多個模型註冊到站點最簡單的方法。admin站點高度可定製,我們將在後面詳細討論其他註冊模型的方法。

建立超級使用者

為了登入admin站點,我們需要一個啟用了Staff狀態的使用者帳戶。為了檢視和建立記錄,我們還需要這個使用者具有管理所有物件的許可權。您可以使用manage.py建立一個具有對站點和所有所需許可權的完全訪問許可權的“超級使用者”帳戶。

在與manage.py相同的目錄中呼叫以下命令以建立超級使用者。系統將提示您輸入使用者名稱、電子郵件地址和密碼。

bash
python3 manage.py createsuperuser

完成此命令後,將向資料庫新增一個新的超級使用者。現在重新啟動開發伺服器,以便我們可以測試登入

bash
python3 manage.py runserver

登入並使用該站點

要登入到站點,請開啟/admin URL(例如http://127.0.0.1:8000/admin)並輸入您的新超級使用者使用者 ID 和密碼憑據(您將被重定向到登入頁面,然後在輸入詳細資訊後返回到/admin URL)。

站點的這部分顯示了我們所有的模型,按已安裝的應用程式分組。您可以單擊模型名稱轉到一個顯示其所有關聯記錄的螢幕,並且您還可以進一步單擊這些記錄以編輯它們。您也可以直接單擊每個模型旁邊的新增連結以開始建立該型別的記錄。

Admin Site - Home page

單擊書籍右側的新增連結以建立一本新書(這將顯示一個類似於下面的對話方塊)。請注意,每個欄位的標題、使用的視窗小部件型別和help_text(如果有)與您在模型中指定的數值相匹配。

為欄位輸入值。您可以透過按相應欄位旁邊的+按鈕來建立新的作者或流派(或者如果您已經建立了它們,則從列表中選擇現有值)。完成後,您可以按儲存儲存並新增另一個儲存並繼續編輯來儲存記錄。

Admin Site - Book Add

注意:在這一點上,我們希望您花一些時間向您的應用程式新增一些書籍、作者、語言和流派(例如奇幻)。確保每個作者和流派都包含幾本不同的書籍(這將使您在以後的文章系列中實現列表和詳細資訊檢視時更加有趣)。

新增完書籍後,單擊頂部書籤中的主頁連結返回到admin頁面。然後單擊書籍連結以顯示當前的書籍列表(或單擊其他連結以檢視其他模型列表)。現在,您已經添加了一些書籍,該列表可能類似於下面的螢幕截圖。每本書的標題都顯示出來;這是在上一篇文章中指定的__str__()方法在Book模型中返回的值。

Admin Site - List of book objects

從這個列表中,您可以透過選中不想保留的書籍旁邊的複選框,從操作下拉列表中選擇刪除…操作,然後按執行按鈕來刪除書籍。您還可以透過按新增書籍按鈕來新增新書籍。

您可以透過選擇連結中的書名來編輯書籍。書籍的編輯頁面(如下所示)與“新增”頁面幾乎相同。主要區別在於頁面標題(更改書籍)以及刪除歷史記錄在站點上檢視按鈕的新增(最後一個按鈕出現是因為我們在模型中定義了get_absolute_url()方法)。

注意:單擊在站點上檢視按鈕會引發NoReverseMatch異常,因為get_absolute_url()方法嘗試反轉()一個尚未定義的命名 URL 對映('book-detail')。我們將在Django教程第6部分:通用列表和詳細資訊檢視中定義 URL 對映和關聯檢視。

Admin Site - Book Edit

現在導航回主頁(使用麵包屑軌跡中的主頁連結),然後檢視作者流派列表——您應該已經從新增新書籍時建立了許多,但您可以隨意新增更多。

您沒有的是任何書籍例項,因為它們不是從書籍建立的(儘管您可以從BookInstance建立Book——這是ForeignKey欄位的性質)。導航回主頁,然後按關聯的新增按鈕以顯示下面的新增書籍例項螢幕。請注意大型的、全域性唯一的 ID,該 ID 可用於單獨識別圖書館中的一本特定書籍。

Admin Site - BookInstance Add

為您的每本書建立多個此類記錄。將至少一些記錄的狀態設定為可用,將其他記錄的狀態設定為借出。如果狀態不是可用,則還應設定將來的到期日期

就是這樣!您現在已經瞭解瞭如何設定和使用管理站點。您還為BookBookInstanceGenreLanguageAuthor建立了記錄,我們將在建立自己的檢視和模板時使用這些記錄。

高階配置

Django 在使用註冊模型中的資訊建立基本管理站點方面做得很好

  • 每個模型都有一個單獨的記錄列表,由使用模型的__str__()方法建立的字串標識,並連結到用於編輯的詳細資訊檢視/表單。預設情況下,此檢視在頂部有一個操作選單,您可以使用它對記錄執行批次刪除操作。
  • 用於編輯和新增記錄的模型詳細資訊記錄表單包含模型中的所有欄位,按宣告順序垂直排列。

您可以進一步定製介面,使其更易於使用。您可以做的一些事情包括

  • 列表檢視
    • 為每個記錄新增要顯示的附加欄位/資訊。
    • 新增過濾器以根據日期或其他選擇值(例如書籍借閱狀態)選擇要列出的記錄。
    • 在列表檢視中的操作選單中新增更多選項,並選擇此選單在表單上的顯示位置。
  • 詳細資訊檢視
    • 選擇要顯示(或排除)的欄位,以及它們的順序、分組、是否可編輯、使用的視窗小部件、方向等。
    • 向記錄新增相關欄位,以允許內聯編輯(例如,在建立作者記錄時新增並編輯書籍記錄的能力)。

在本節中,我們將檢視一些更改,這些更改將改進我們的LocalLibrary的介面,包括向BookAuthor模型列表新增更多資訊,並改進其編輯檢視的佈局。我們不會更改LanguageGenre模型的演示,因為它們每個只有一個欄位,因此這樣做沒有實際好處!

您可以在Django Admin站點(Django 文件)中找到所有管理站點定製選擇的完整參考。

註冊 ModelAdmin 類

要更改模型在管理介面中的顯示方式,請定義一個ModelAdmin類(它描述了佈局),並將其註冊到模型。

讓我們從Author模型開始。開啟目錄應用程式中的admin.py/django-locallibrary-tutorial/catalog/admin.py)。將您最初的Author模型註冊註釋掉(在其前面加上一個 #)。

python
# admin.site.register(Author)

現在新增一個新的AuthorAdmin和註冊,如下所示。

python
# Define the admin class
class AuthorAdmin(admin.ModelAdmin):
    pass

# Register the admin class with the associated model
admin.site.register(Author, AuthorAdmin)

現在,我們將為BookBookInstance新增ModelAdmin類。我們再次需要註釋掉原始註冊

python
# admin.site.register(Book)
# admin.site.register(BookInstance)

現在建立並註冊新模型;為了進行演示,我們將改用@register裝飾器來註冊模型(這與admin.site.register()語法完全相同)

python
# Register the Admin classes for Book using the decorator
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    pass

# Register the Admin classes for BookInstance using the decorator
@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
    pass

目前,我們所有的管理類都是空的(請參閱pass),因此管理行為將保持不變!我們現在可以擴充套件它們以定義我們特定於模型的管理行為。

配置列表檢視

LocalLibrary目前使用從模型__str__()方法生成的物體名稱來列出所有作者。當您只有幾個作者時,這很好,但是當您有很多作者時,您最終可能會出現重複項。為了區分它們,或者僅僅是因為您想顯示有關每個作者的更多有趣資訊,您可以使用list_display在檢視中新增更多欄位。

將您的AuthorAdmin類替換為下面的程式碼。要在列表中顯示的欄位名稱在所需的順序中以元組形式宣告,如所示(這些名稱與您最初的模型中指定的名稱相同)。

python
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')

現在導航到您網站中的作者列表。上面的欄位現在應該顯示,如下所示

Admin Site - Improved Author List

對於我們的Book 模型,我們將額外顯示authorgenreauthor 是一個ForeignKey 欄位(一對多)關係,因此將由關聯記錄的__str__() 值表示。將BookAdmin 類替換為以下版本。

python
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'display_genre')

不幸的是,我們不能直接在list_display 中指定genre 欄位,因為它是一個ManyToManyField(Django 阻止了這種情況,因為這樣做會產生很大的資料庫訪問“成本”)。相反,我們將定義一個display_genre 函式來獲取資訊作為字串(這是我們在上面呼叫的函式;我們將在下面定義它)。

注意: 獲取genre 這裡可能不是一個好主意,因為資料庫操作的“成本”。我們向您展示如何做,因為在模型中呼叫函式在其他情況下非常有用——例如,在列表中的每個專案旁邊新增一個刪除連結。

將以下程式碼新增到您的Book 模型(models.py)中。這將從genre 欄位的前三個值(如果存在)建立一個字串,並建立一個可以在管理站點中用於此方法的short_description

python
def display_genre(self):
    """Create a string for the Genre. This is required to display genre in Admin."""
    return ', '.join(genre.name for genre in self.genre.all()[:3])

display_genre.short_description = 'Genre'

儲存模型和更新的管理介面後,開啟您的網站並轉到書籍列表頁面;您應該會看到如下所示的書籍列表

Admin Site - Improved Book List

Genre 模型(以及Language 模型,如果您定義了一個)都只有一個欄位,因此沒有必要為它們建立額外的模型來顯示其他欄位。

注意: 值得更新BookInstance 模型列表,以至少顯示狀態和預期的歸還日期。我們在本文末尾添加了一個挑戰作為挑戰!

新增列表過濾器

當列表中有很多專案時,能夠過濾顯示哪些專案會很有用。這可以透過在list_filter 屬性中列出欄位來完成。將您當前的BookInstanceAdmin 類替換為以下程式碼片段。

python
class BookInstanceAdmin(admin.ModelAdmin):
    list_filter = ('status', 'due_back')

列表檢視現在將在右側包含一個過濾器框。注意您如何選擇日期和狀態來過濾值

Admin Site - BookInstance List Filters

組織詳細資訊檢視佈局

預設情況下,詳細資訊檢視將所有欄位垂直排列,按照它們在模型中的宣告順序排列。您可以更改宣告順序,哪些欄位顯示(或排除),是否使用部分來組織資訊,欄位是水平顯示還是垂直顯示,甚至在管理表單中使用什麼編輯小部件。

注意:LocalLibrary 模型相對簡單,因此我們不需要大量更改佈局;然而,我們還是會做一些更改,只是為了向您展示如何做。

控制顯示和排列哪些欄位

更新您的AuthorAdmin 類以新增fields 行,如下所示

python
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')

    fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]

fields 屬性僅列出了要在表單中顯示的欄位,按順序排列。預設情況下,欄位會垂直顯示,但如果將它們進一步分組在一個元組中(如上面的“日期”欄位所示),則會水平顯示。

在您的網站上,轉到作者詳細資訊檢視——它現在應該顯示如下

Admin Site - Improved Author Detail

注意:您還可以使用exclude 屬性來宣告要從表單中排除的屬性列表(模型中的所有其他屬性都將顯示)。

對詳細資訊檢視進行分割槽

您可以使用fieldsets 屬性,在詳細資訊表單內新增“部分”來對相關的模型資訊進行分組。

BookInstance 模型中,我們有與書籍本身相關的資訊(即nameimprintid),以及它何時可用(statusdue_back)。我們可以使用fieldsets 屬性,將這些新增到我們的BookInstanceAdmin 類中,如下所示。

python
@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
    list_filter = ('status', 'due_back')

    fieldsets = (
        (None, {
            'fields': ('book', 'imprint', 'id')
        }),
        ('Availability', {
            'fields': ('status', 'due_back')
        }),
    )

每個部分都有自己的標題(或None,如果您不想要標題)以及一個與之關聯的欄位元組字典——格式難以描述,但如果您檢視上面的程式碼片段,則很容易理解。

現在導航到您的網站中的書籍例項檢視;表單應該顯示如下

Admin Site - Improved BookInstance Detail with sections

關聯記錄的內聯編輯

有時,能夠同時新增關聯記錄是有意義的。例如,在同一個詳細資訊頁面上同時擁有書籍資訊和您所擁有特定副本的資訊可能是有意義的。

您可以透過宣告inlines 來實現這一點,該內聯的型別為TabularInline(水平佈局)或StackedInline(垂直佈局,與預設模型佈局相同)。您可以透過在您的BookAdmin 中指定inlines,將BookInstance 資訊內聯新增到我們的Book 詳細資訊中

python
class BooksInstanceInline(admin.TabularInline):
    model = BookInstance

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'display_genre')

    inlines = [BooksInstanceInline]

現在導航到您的網站中Book 的檢視——在底部,您現在應該看到與該書籍相關的書籍例項(緊接在書籍的型別欄位下方)

Admin Site - Book with Inlines

在這種情況下,我們所做的只是聲明瞭我們的表格內聯類,它只是添加了來自內聯模型的所有欄位。您可以為佈局指定各種其他資訊,包括要顯示的欄位、它們的順序、它們是否為只讀等等(有關更多資訊,請參閱TabularInline)。

注意:此功能有一些令人痛苦的限制!在上圖中,我們有三個現有的書籍例項,後面是三個新的書籍例項的佔位符(它們看起來非常相似!)。最好預設情況下沒有多餘的書籍例項,只需使用新增另一個書籍例項連結新增它們,或者能夠從這裡以不可讀連結的形式列出BookInstance。第一個選項可以透過在BooksInstanceInline 模型中將extra 屬性設定為0 來完成,您可以自己嘗試。

挑戰自己

在本節中,我們學到了很多東西,所以現在是您嘗試一些東西的時候了。

  1. 對於BookInstance 列表檢視,新增程式碼以顯示書籍、狀態、應還日期和 ID(而不是預設的__str__() 文字)。
  2. 使用與我們為Book/BookInstance 所做的相同方法,將Book 專案的內聯列表新增到Author 詳細資訊檢視中。

總結

就是這樣!您現在已經學會了如何在最簡單和改進的形式下設定管理站點,如何建立超級使用者,以及如何導航管理站點並檢視、刪除和更新記錄。在此過程中,您建立了一堆書籍、書籍例項、型別和作者,我們將在建立自己的檢視和模板後能夠列出和顯示它們。

進一步閱讀