撰寫你的第一個 Django 應用程式,第 7 部分¶
本教學課程從教學課程 6結束的地方開始。我們將繼續進行網頁投票應用程式,並專注於自訂 Django 自動產生的管理網站,我們在教學課程 2中首次探索了該網站。
哪裡可以獲得協助
如果您在學習本教學課程時遇到問題,請前往常見問題的取得協助章節。
自訂管理表單¶
透過使用 admin.site.register(Question)
註冊 Question
模型,Django 能夠建構預設的表單表示。通常,您會想要自訂管理表單的外觀和運作方式。您會在註冊物件時告訴 Django 您想要的選項來執行此操作。
讓我們看看它是如何運作的,方法是重新排序編輯表單上的欄位。將 admin.site.register(Question)
行替換為
polls/admin.py
¶from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fields = ["pub_date", "question_text"]
admin.site.register(Question, QuestionAdmin)
您將遵循此模式 - 建立一個模型管理類別,然後在需要變更模型的管理選項時,將其作為第二個引數傳遞給 admin.site.register()
。
上面的這個特定變更會使「發佈日期」出現在「問題」欄位之前

只有兩個欄位時,這並沒有什麼了不起,但是對於有數十個欄位的管理表單,選擇直覺的順序是很重要的可用性細節。
說到有數十個欄位的表單,您可能想要將表單分成多個欄位集
polls/admin.py
¶from django.contrib import admin
from .models import Question
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {"fields": ["question_text"]}),
("Date information", {"fields": ["pub_date"]}),
]
admin.site.register(Question, QuestionAdmin)
fieldsets
中每個 tuple 的第一個元素是欄位集的標題。以下是我們現在的表單外觀

自訂管理變更清單¶
現在 Question 管理頁面看起來不錯,讓我們對「變更清單」頁面進行一些調整 - 該頁面會顯示系統中的所有問題。
以下是目前的外觀

預設情況下,Django 會顯示每個物件的 str()
。但有時,如果我們可以顯示個別欄位會更有幫助。若要執行此操作,請使用 list_display
管理員選項,這是要顯示在物件的變更清單頁面上的欄位名稱清單(作為欄)。
polls/admin.py
¶class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date"]
為了謹慎起見,我們也加入教學課程 2的 was_published_recently()
方法
polls/admin.py
¶class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ["question_text", "pub_date", "was_published_recently"]
現在問題變更清單頁面如下所示

您可以點擊欄標題以按這些值排序 - 除了 was_published_recently
標頭的情況,因為不支援按任意方法的輸出排序。另請注意,was_published_recently
的欄標頭預設為該方法的名稱(底線會以空格取代),並且每行都包含輸出的字串表示形式。
您可以使用該方法上的 display()
修飾器(擴充在教學課程 2中建立的 polls/models.py
檔案)來改善這一點,如下所示
polls/models.py
¶from django.contrib import admin
class Question(models.Model):
# ...
@admin.display(
boolean=True,
ordering="pub_date",
description="Published recently?",
)
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
如需透過修飾器設定的屬性的詳細資訊,請參閱list_display
。
再次編輯您的 polls/admin.py
檔案,並在 Question
變更清單頁面中新增改進:使用 list_filter
進行篩選。將以下行新增至 QuestionAdmin
list_filter = ["pub_date"]
這會新增一個「篩選器」側邊欄,讓使用者可以按 pub_date
欄位篩選變更清單

顯示的篩選器類型取決於您篩選的欄位類型。由於 pub_date
是一個 DateTimeField
,Django 知道要提供適當的篩選選項:「任何日期」、「今天」、「過去 7 天」、「本月」、「今年」。
這樣看來進展不錯。讓我們加入一些搜尋功能。
search_fields = ["question_text"]
這會在變更列表的頂部加入一個搜尋框。當有人輸入搜尋詞時,Django 會搜尋 question_text
欄位。您可以根據需要使用任意多個欄位 – 雖然因為它在底層使用 LIKE
查詢,所以將搜尋欄位數量限制在合理的範圍內,會讓您的資料庫更容易執行搜尋。
現在也是時候注意到,變更列表會免費提供您分頁功能。預設是每頁顯示 100 個項目。變更 列表 分頁
、搜尋 框
、篩選器
、日期階層
和 欄位標題排序
都會如您所想般地協同運作。
自訂管理介面的外觀和風格¶
顯然,在每個管理頁面的頂部都顯示「Django administration」是荒謬的。這只是佔位符文字。
不過,您可以使用 Django 的範本系統來變更它。Django 管理介面本身就是由 Django 提供支援,且其介面使用 Django 自己的範本系統。
自訂您的*專案*範本¶
在您的 djangotutorial
目錄中建立一個 templates
目錄。範本可以放在 Django 可以存取的檔案系統上的任何位置。(Django 會以您的伺服器運行的使用者身份運行。)但是,將您的範本保留在專案內是一個很好的慣例。
開啟您的設定檔(mysite/settings.py
,請記得),並在 TEMPLATES
設定中新增 DIRS
選項。
mysite/settings.py
¶TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
DIRS
是一個檔案系統目錄清單,用於在載入 Django 範本時進行檢查;它是一個搜尋路徑。
組織範本
就像靜態檔案一樣,我們*可以*將所有範本放在一起,放在一個大的範本目錄中,這樣做也能完美運作。但是,屬於特定應用程式的範本應放在該應用程式的範本目錄中(例如 polls/templates
),而不是專案的範本目錄 (templates
)。我們會在可重複使用的應用程式教學中更詳細地討論*為什麼*要這樣做。
現在,在 templates
內建立一個名為 admin
的目錄,並將範本 admin/base_site.html
從 Django 原始碼中預設的 Django 管理範本目錄(django/contrib/admin/templates)複製到該目錄中。
Django 原始碼檔案在哪裡?
如果您在系統上找不到 Django 原始碼檔案的位置,請執行以下命令
$ python -c "import django; print(django.__path__)"
...\> py -c "import django; print(django.__path__)"
然後,編輯該檔案,並將 {{ site_header|default:_('Django administration') }}
(包括大括號)取代為您自己網站的名稱,如同您認為合適的一樣。您應該會得到如下所示的程式碼區段:
{% block branding %}
<div id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></div>
{% if user.is_anonymous %}
{% include "admin/color_theme_toggle.html" %}
{% endif %}
{% endblock %}
我們使用這種方法來教您如何覆寫範本。在實際專案中,您可能會使用 django.contrib.admin.AdminSite.site_header
屬性,以更輕鬆地進行此特定自訂。
這個範本檔案包含許多像 {% block branding %}
和 {{ title }}
的文字。{%
和 {{
標籤是 Django 範本語言的一部分。當 Django 呈現 admin/base_site.html
時,這個範本語言將會被評估,以產生最終的 HTML 頁面,就像我們在教學 3中看到的那樣。
請注意,任何 Django 的預設管理範本都可以被覆寫。要覆寫範本,請執行與您對 base_site.html
所做的相同操作 - 將其從預設目錄複製到您的自訂目錄中,然後進行變更。
自訂您的*應用程式*範本¶
精明的讀者會問:但是如果 DIRS
預設為空,那麼 Django 是如何找到預設的管理範本的呢?答案是,由於 APP_DIRS
設定為 True
,Django 會自動在每個應用程式套件中尋找一個 templates/
子目錄,以作為回退(別忘了 django.contrib.admin
也是一個應用程式)。
我們的投票應用程式不是很複雜,不需要自訂管理範本。但是,如果它變得更複雜,並且需要修改 Django 的標準管理範本來實現其某些功能,那麼修改*應用程式*的範本,而不是修改*專案*中的範本會更合理。這樣一來,您就可以將投票應用程式包含在任何新專案中,並確保它可以找到它需要的自訂範本。
請參閱範本載入文件,以取得關於 Django 如何尋找範本的更多資訊。
自訂管理索引頁面¶
同樣地,您可能想要自訂 Django 管理索引頁面的外觀和風格。
預設情況下,它會按照字母順序列出所有在管理應用程式中註冊的 INSTALLED_APPS
中的應用程式。您可能想要對版面配置進行重大變更。畢竟,索引可能是管理介面中最重要的頁面,它應該易於使用。
要自訂的範本是 admin/index.html
。(執行與上一節中 admin/base_site.html
相同的操作 – 將其從預設目錄複製到您的自訂範本目錄)。編輯該檔案,您會看到它使用一個名為 app_list
的範本變數。該變數包含每個已安裝的 Django 應用程式。您可以不使用它,而是以您認為最佳的任何方式,將連結硬編碼到特定物件的管理頁面。
當您熟悉管理介面後,請閱讀本教學的第 8 部分,以學習如何使用第三方套件。