Django4.0 開始-編寫你的第一個Django應用,第7部分

2022-09-03 09:34 更新

自定義后臺表單

通過 ?admin.site.register(Question)? 注冊 ?Question ?模型,Django 能夠構建一個默認的表單用于展示。通常來說,你期望能自定義表單的外觀和工作方式。你可以在注冊模型時將這些設置告訴 Django。
讓我們通過重排列表單上的字段來看看它是怎么工作的。用以下內容替換 ?admin.site.register(Question)?:

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question_text']

admin.site.register(Question, QuestionAdmin)

你需要遵循以下流程——創(chuàng)建一個模型后臺類,接著將其作為第二個參數(shù)傳給 ?admin.site.register() ?——在你需要修改模型的后臺管理選項時這么做。
以上修改使得 "Publication date" 字段顯示在 "Question" 字段之前:

admin07


只有兩個字段并不令人印象深刻,但對于具有數(shù)十個字段的管理表單,選擇直觀的順序是一個重要的可用性細節(jié)。

說到具有數(shù)十個字段的表單,您可能希望將表單拆分為字段集:

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元組中的第一個元素是字段集的標題。以下是我們的表單現(xiàn)在的樣子:

admin08t

添加關聯(lián)的對象

好了,現(xiàn)在我們有了投票的后臺頁。不過,一個 ?Question ?有多個 ?Choice?,但后臺頁卻沒有顯示多個選項。
有兩個方法可以解決這個問題。第一個就是仿照我們向后臺注冊 ?Question ?一樣注冊 ?Choice ?:

from django.contrib import admin

from .models import Choice, Question
# ...
admin.site.register(Choice)

現(xiàn)在 "Choices" 在 Django 后臺頁中是一個可用的選項了?!疤砑舆x項”的表單看起來像這樣:

admin09

在這個表單中,"Question" 字段是一個包含數(shù)據(jù)庫中所有投票的選擇框。Django 知道要將 ?ForeignKey在后臺中以選擇框 ?<select>? 的形式展示。此時,我們只有一個投票。

同時也注意下 "Question" 旁邊的“添加”按鈕。每個使用 ?ForeignKey ?關聯(lián)到另一個對象的對象會自動獲得這個功能。當你點擊“添加”按鈕時,你會見到一個包含“添加投票”的表單。如果你在這個彈出框中添加了一個投票,并點擊了“保存”,Django 會將其保存至數(shù)據(jù)庫,并動態(tài)地在你正在查看的“添加選項”表單中選中它。

不過,這是一種很低效地添加“選項”的方法。更好的辦法是在你創(chuàng)建“投票”對象時直接添加好幾個選項。讓我們實現(xiàn)它。
移除調用 ?register()? 注冊 ?Choice ?模型的代碼。隨后,像這樣修改 ?Question ?的注冊代碼:

from django.contrib import admin

from .models import Choice, Question


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


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

admin.site.register(Question, QuestionAdmin)

這會告訴 Django:“?Choice ?對象要在 ?Question ?后臺頁面編輯。默認提供 3 個足夠的選項字段。”
加載“添加投票”頁面來看看它長啥樣:

admin10t

它看起來像這樣:有三個關聯(lián)的選項插槽——由 ?extra ?定義,且每次你返回任意已創(chuàng)建的對象的“修改”頁面時,你會見到三個新的插槽。
在三個插槽的末端,你會看到一個“添加新選項”的按鈕。如果你單擊它,一個新的插槽會被添加。如果你想移除已有的插槽,可以點擊插槽右上角的X。以下圖片展示了一個已添加的插槽:

admin14t

不過,仍然有點小問題。它占據(jù)了大量的屏幕區(qū)域來顯示所有關聯(lián)的 ?Choice ?對象的字段。對于這個問題,Django 提供了一種表格式的單行顯示關聯(lián)對象的方法。要使用它,只需按如下形式修改 ?ChoiceInline ?申明:

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

通過 ?TabularInline ?(替代 ?StackedInline ?),關聯(lián)對象以一種表格式的方式展示,顯得更加緊湊:

admin11t

注意這里有一個額外的“刪除”列,這允許移除通過“添加新選項”按鈕添加的,或是已被保存的行。

自定義后臺更改列表

現(xiàn)在投票的后臺頁看起來很不錯,讓我們對“更改列表”頁面進行一些調整——改成一個能展示系統(tǒng)中所有投票的頁面。

以下是它此時的外觀:

admin04t (1)

默認情況下,Django 顯示每個對象的 ?str()? 返回的值。但有時如果我們能夠顯示單個字段,它會更有幫助。為此,使用 ?list_display ?后臺選項,它是一個包含要顯示的字段名的元組,在更改列表頁中以列的形式展示這個對象:

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date')

另外,讓我們把 教程第 2 部分 中的 ?was_published_recently()? 方法也加上:

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date', 'was_published_recently')

現(xiàn)在修改投票的列表頁看起來像這樣:

admin12t

你可以點擊列標題來對這些行進行排序——除了 ?was_published_recently ?這個列,因為沒有實現(xiàn)排序方法。順便看下這個列的標題 ?was_published_recently?,默認就是方法名(用空格替換下劃線),該列的每行都以字符串形式展示出處。
你可以通過在該方法上(在 ?polls/models.py? 中)使用 ?display()? 裝飾器來改進,如下圖所示:

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

再次編輯文件 ?polls/admin.py?,優(yōu)化 ?Question變更頁:過濾器,使用 ?list_filter?。將以下代碼添加至 ?QuestionAdmin?:

list_filter = ['pub_date']

這樣做添加了一個“過濾器”側邊欄,允許人們以 ?pub_date ?字段來過濾列表:

admin13t

展示的過濾器類型取決你你要過濾的字段的類型。因為 ?pub_date ?是類 ?DateTimeField?,Django 知道要提供哪個過濾器:“任意時間”,“今天”,“過去7天”,“這個月”和“今年”。
這已經(jīng)弄的很好了。讓我們再擴充些功能:

search_fields = ['question_text']

在列表的頂部增加一個搜索框。當輸入待搜項時,?Django ?將搜索 ?question_text ?字段。你可以使用任意多的字段——由于后臺使用 ?LIKE ?來查詢數(shù)據(jù),將待搜索的字段數(shù)限制為一個不會出問題大小,會便于數(shù)據(jù)庫進行查詢操作。
現(xiàn)在是給你的修改列表頁增加分頁功能的好時機。默認每頁顯示 100 項。變更頁分頁, 搜索框, 過濾器, 日期層次結構, 和 列標題排序 均以你期望的方式合作運行。

自定義后臺界面和風格

在每個后臺頁頂部顯示“Django 管理員”顯得很滑稽。這只是一串占位文本。
不過,你可以通過 Django 的模板系統(tǒng)來修改。Django 的后臺由自己驅動,且它的交互接口采用 Django 自己的模板系統(tǒng)。

自定義你的工程模板

在你的工程目錄(指包含 ?manage.py? 的那個文件夾)內創(chuàng)建一個名為 ?templates ?的目錄。模板可放在你系統(tǒng)中任何 Django 能找到的位置。(誰啟動了 Django,Django 就以他的用戶身份運行。)不過,把你的模板放在工程內會帶來很大便利,推薦你這樣做。
打開你的設置文件(?mysite/settings.py?,牢記),在 ?TEMPLATES ?設置中添加 ?DIRS ?選項:

?DIRS ?中只需填寫模板路徑即可

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 ?是一個包含多個系統(tǒng)目錄的文件列表,用于在載入 Django 模板時使用,是一個待搜索路徑。

現(xiàn)在,在 ?templates ?目錄內創(chuàng)建名為 ?admin ?的目錄,隨后,將存放 Django 默認模板的目錄(?django/contrib/admin/templates?)內的模板文件 ?admin/base_site.html? 復制到這個目錄內。

接著,用你網(wǎng)頁站點的名字編輯替換文件內的 ?{{ site_header|default:_('Django administration') }}? (包含大括號)。完成后,你應該看到如下代碼:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

我們會用這個方法來教你復寫模板。在一個實際工程中,你可能更期望使用 ?django.contrib.admin.AdminSite.site_header? 來進行簡單的定制。
這個模板文件包含很多類似 ?{% block branding %}? 和 ?{{ title }}? 的文本。 ?{%? 和 ?{{? 標簽是 Django 模板語言的一部分。當 Django 渲染 ?admin/base_site.html? 時,這個模板語言會被求值,生成最終的網(wǎng)頁,就像我們在 教程第 3 部分 所學的一樣。
注意,所有的 Django 默認后臺模板均可被復寫。若要復寫模板,像你修改 ?base_site.html? 一樣修改其它文件——先將其從默認目錄中拷貝到你的自定義目錄,再做修改。

自定義你應用的模板

機智的同學可能會問: ?DIRS ?默認是空的,Django 是怎么找到默認的后臺模板的?因為 ?APP_DIRS ?被置為 ?True?,Django 會自動在每個應用包內遞歸查找 ?templates/? 子目錄(不要忘了 ?django.contrib.admin? 也是一個應用)。
我們的投票應用不是非常復雜,所以無需自定義后臺模板。不過,如果它變的更加復雜,需要修改 Django 的標準后臺模板功能時,修改 應用 的模板會比 工程 的更加明智。這樣,在其它工程包含這個投票應用時,可以確保它總是能找到需要的自定義模板文件。

自定義后臺主頁

在類似的說明中,你可能想要自定義 Django 后臺索引頁的外觀。
默認情況下,它展示了所有配置在 ?INSTALLED_APPS ?中,已通過后臺應用注冊,按拼音排序的應用。你可能想對這個頁面的布局做重大的修改。畢竟,索引頁是后臺的重要頁面,它應該便于使用。
需要自定義的模板是 ?admin/index.html?。(像上一節(jié)修改 ?admin/base_site.html? 那樣修改此文件——從默認目錄中拷貝此文件至自定義模板目錄)。打開此文件,你將看到它使用了一個叫做 ?app_list ?的模板變量。這個變量包含了每個安裝的 Django 應用。你可以用任何你期望的硬編碼鏈接(鏈接至特定對象的管理頁)替代使用這個變量。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號