第七章

這篇教程承接?教程第 6 部分?結(jié)束的地方。我們繼續(xù)修改在線投票應(yīng)用,這次我們專注于自定義我們?cè)?教程第 2 部分?初見過(guò)的 Django 自動(dòng)生成后臺(tái)的過(guò)程。

自定義后臺(tái)表單?

通過(guò)?admin.site.register(Question)?注冊(cè)?Question?模型,Django 能夠構(gòu)建一個(gè)默認(rèn)的表單用于展示。通常來(lái)說(shuō),你期望能自定義表單的外觀和工作方式。你可以在注冊(cè)模型時(shí)將這些設(shè)置告訴 Django。

讓我們通過(guò)重排列表單上的字段來(lái)看看它是怎么工作的。用以下內(nèi)容替換?admin.site.register(Question):

polls/admin.py

fromdjango.contribimportadminfrom.modelsimportQuestionclassQuestionAdmin(admin.ModelAdmin):fields=['pub_date','question_text']admin.site.register(Question,QuestionAdmin)

你需要遵循以下流程——?jiǎng)?chuàng)建一個(gè)模型后臺(tái)類,接著將其作為第二個(gè)參數(shù)傳給?admin.site.register()?——在你需要修改模型的后臺(tái)管理選項(xiàng)時(shí)這么做。

以上修改使得 "Publication date" 字段顯示在 "Question" 字段之前:

這在只有兩個(gè)字段時(shí)顯得沒(méi)啥卵用,但對(duì)于擁有數(shù)十個(gè)字段的表單來(lái)說(shuō),為表單選擇一個(gè)直觀的排序方法就顯得你的針很細(xì)了。

說(shuō)到擁有數(shù)十個(gè)字段的表單,你可能更期望將表單分為幾個(gè)字段集:

polls/admin.py

fromdjango.contribimportadminfrom.modelsimportQuestionclassQuestionAdmin(admin.ModelAdmin):fieldsets=[(None,{'fields':['question_text']}),('Date information',{'fields':['pub_date']}),]admin.site.register(Question,QuestionAdmin)

fieldsets?元組中的第一個(gè)元素是字段集的標(biāo)題。以下是我們的表單現(xiàn)在的樣子:

添加關(guān)聯(lián)的對(duì)象?

好了,現(xiàn)在我們有了投票的后臺(tái)頁(yè)。不過(guò),一個(gè)?Question?有多個(gè)?Choice,但后臺(tái)頁(yè)卻沒(méi)有顯示多個(gè)選項(xiàng)。

好了。

有兩個(gè)方法可以解決這個(gè)問(wèn)題。第一個(gè)就是仿照我們向后臺(tái)注冊(cè)?Question?一樣注冊(cè)?Choice?。這很簡(jiǎn)單:

polls/admin.py

fromdjango.contribimportadminfrom.modelsimportChoice,Question# ...admin.site.register(Choice)

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

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

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

不過(guò),這是一種很低效地添加“選項(xiàng)”的方法。更好的辦法是在你創(chuàng)建“投票”對(duì)象時(shí)直接添加好幾個(gè)選項(xiàng)。讓我們實(shí)現(xiàn)它。

移除調(diào)用?register()?注冊(cè)?Choice?模型的代碼。隨后,像這樣修改?Question?的注冊(cè)代碼:

polls/admin.py

fromdjango.contribimportadminfrom.modelsimportChoice,QuestionclassChoiceInline(admin.StackedInline):model=Choiceextra=3classQuestionAdmin(admin.ModelAdmin):fieldsets=[(None,{'fields':['question_text']}),('Date information',{'fields':['pub_date'],'classes':['collapse']}),]inlines=[ChoiceInline]admin.site.register(Question,QuestionAdmin)

這會(huì)告訴 Django:“Choice?對(duì)象要在?Question?后臺(tái)頁(yè)面編輯。默認(rèn)提供 3 個(gè)足夠的選項(xiàng)字段?!?/p>

加載“添加投票”頁(yè)面來(lái)看看它長(zhǎng)啥樣:

它看起來(lái)像這樣:有三個(gè)關(guān)聯(lián)的選項(xiàng)插槽——由?extra?定義,且每次你返回任意已創(chuàng)建的對(duì)象的“修改”頁(yè)面時(shí),你會(huì)見到三個(gè)新的插槽。

在三個(gè)插槽的末端,你會(huì)看到一個(gè)“添加新選項(xiàng)”的按鈕。如果你單擊它,一個(gè)新的插槽會(huì)被添加。如果你想移除已有的插槽,可以點(diǎn)擊插槽右上角的X。注意,你不能移除原始的 3 個(gè)插槽。以下圖片展示了一個(gè)已添加的插槽:

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

polls/admin.py

classChoiceInline(admin.TabularInline):#...

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

注意這里有一個(gè)額外的“刪除?”列,這允許移除通過(guò)“添加新選項(xiàng)”按鈕添加的,或是已被保存的行。

自定義后臺(tái)更改列表?

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

以下是它此時(shí)的外觀:

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

polls/admin.py

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

為了更好用,讓我們也包含?教程第 2 部分?中的?was_published_recently()?方法:

polls/admin.py

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

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

你可以點(diǎn)擊列標(biāo)題來(lái)對(duì)這些行進(jìn)行排序——除了?was_published_recently?這個(gè)列,因?yàn)闆](méi)有實(shí)現(xiàn)排序方法。順便看下這個(gè)列的標(biāo)題?was_published_recently,默認(rèn)就是方法名(用空格替換下劃線),該列的每行都以字符串形式展示出處。

你可以通過(guò)給這個(gè)方法(在?polls/models.py?中)一些屬性來(lái)達(dá)到優(yōu)化的目的,像這樣:

polls/models.py

classQuestion(models.Model):# ...defwas_published_recently(self):now=timezone.now()returnnow-datetime.timedelta(days=1)<=self.pub_date<=nowwas_published_recently.admin_order_field='pub_date'was_published_recently.boolean=Truewas_published_recently.short_description='Published recently?'

更多關(guān)于這些方法屬性的信息,參見?list_display

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

list_filter=['pub_date']

這樣做添加了一個(gè)“過(guò)濾器”側(cè)邊欄,允許人們以?pub_date?字段來(lái)過(guò)濾列表:

展示的過(guò)濾器類型取決你你要過(guò)濾的字段的類型。因?yàn)?pub_date?是類?DateTimeField,Django 知道要提供哪個(gè)過(guò)濾器:“任意時(shí)間”,“今天”,“過(guò)去7天”,“這個(gè)月”和“今年”。

這已經(jīng)弄的很好了。讓我們?cè)贁U(kuò)充些功能:

search_fields=['question_text']

在列表的頂部增加一個(gè)搜索框。當(dāng)輸入待搜項(xiàng)時(shí),Django 將搜索?question_text?字段。你可以使用任意多的字段——由于后臺(tái)使用?LIKE?來(lái)查詢數(shù)據(jù),將待搜索的字段數(shù)限制為一個(gè)不會(huì)出問(wèn)題大小,會(huì)便于數(shù)據(jù)庫(kù)進(jìn)行查詢操作。

現(xiàn)在是給你的修改列表頁(yè)增加分頁(yè)功能的好時(shí)機(jī)。默認(rèn)每頁(yè)顯示 100 項(xiàng)。變更頁(yè)分頁(yè),?搜索框,?過(guò)濾器,?日期層次結(jié)構(gòu), 和?列標(biāo)題排序?均以你期望的方式合作運(yùn)行。

自定義后臺(tái)界面和風(fēng)格?

在每個(gè)后臺(tái)頁(yè)頂部顯示“Django 管理員”顯得很滑稽。這只是一串占位文本。

不過(guò),這可以通過(guò) Django 的模板系統(tǒng)很方便的修改。Django 的后臺(tái)由自己驅(qū)動(dòng),且它的交互接口采用 Django 自己的模板系統(tǒng)。

自定義你的?工程的?模板?

在你的工程目錄(指包含?manage.py?的那個(gè)文件夾)內(nèi)創(chuàng)建一個(gè)名為?templates?的目錄。模板可放在你系統(tǒng)中任何 Django 能找到的位置。(誰(shuí)啟動(dòng)了 Django,Django 就以他的用戶身份運(yùn)行。)不過(guò),把你的模板放在工程內(nèi)會(huì)帶來(lái)很大便利,推薦你這樣做。

打開你的設(shè)置文件(mysite/settings.py,牢記),在?TEMPLATES?設(shè)置中添加?DIRS?選項(xiàng):

mysite/settings.py

TEMPLATES=[{'BACKEND':'django.template.backends.django.DjangoTemplates','DIRS':[os.path.join(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?是一個(gè)包含多個(gè)系統(tǒng)目錄的文件列表,用于在載入 Django 模板時(shí)使用,是一個(gè)待搜索路徑。

組織模板

就像靜態(tài)文件一樣,我們?可以?把所有的模板文件放在一個(gè)大模板目錄內(nèi),這樣它也能工作的很好。但是,屬于特定應(yīng)用的模板文件最好放在應(yīng)用所屬的模板目錄(例如?polls/templates),而不是工程的模板目錄(templates)。我們會(huì)在?創(chuàng)建可復(fù)用的應(yīng)用教程?中討論?為什么?我們要這樣做。

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

Django 的源文件在哪里?

如果你不知道 Django 源碼在你系統(tǒng)的哪個(gè)位置,運(yùn)行以下命令:

$python -c"import django; print(django.__path__)"

接著,用你站點(diǎn)的名字替換文件內(nèi)的?``{{ site_header|default:_('Django administration') }}``(包含大括號(hào))。完成后,你應(yīng)該看到如下代碼:

{%blockbranding%}<h1id="site-name"><ahref="{%url'admin:index'%}">Polls Administration</a></h1>{%endblock%}

我們會(huì)用這個(gè)方法來(lái)教你復(fù)寫模板。在一個(gè)實(shí)際工程中,你可能更期望使用?django.contrib.admin.AdminSite.site_header?來(lái)進(jìn)行簡(jiǎn)單的定制。

這個(gè)模板文件包含很多類似?{%?block?branding?%}?和?{{?title?}}?的文本。?{%?和?{{?標(biāo)簽是 Django 模板語(yǔ)言的一部分。當(dāng) Django 渲染?admin/base_site.html?時(shí),這個(gè)模板語(yǔ)言會(huì)被求值,生成最終的網(wǎng)頁(yè),就像我們?cè)?教程第 3 部分?所學(xué)的一樣。

注意,所有的 Django 默認(rèn)后臺(tái)模板均可被復(fù)寫。若要復(fù)寫模板,像你修改?base_site.html?一樣修改其它文件——先將其從默認(rèn)目錄中拷貝到你的自定義目錄,再做修改。

自定義你?應(yīng)用的?模板?

機(jī)智的同學(xué)可能會(huì)問(wèn):?DIRS?默認(rèn)是空的,Django 是怎么找到默認(rèn)的后臺(tái)模板的?因?yàn)?APP_DIRS?被置為?True,Django 會(huì)自動(dòng)在每個(gè)應(yīng)用包內(nèi)遞歸查找?templates/?子目錄(不要忘了?django.contrib.admin?也是一個(gè)應(yīng)用)。

我們的投票應(yīng)用不是非常復(fù)雜,所以無(wú)需自定義后臺(tái)模板。不過(guò),如果它變的更加復(fù)雜,需要修改 Django 的標(biāo)準(zhǔn)后臺(tái)模板功能時(shí),修改?應(yīng)用?的模板會(huì)比?工程?的更加明智。這樣,在其它工程包含這個(gè)投票應(yīng)用時(shí),可以確保它總是能找到需要的自定義模板文件。

更多關(guān)于 Django 如何查找模板的文檔,參見?加載模板文檔。

自定義后臺(tái)主頁(yè)?

在類似的說(shuō)明中,你可能想要自定義 Django 后臺(tái)索引頁(yè)的外觀。

默認(rèn)情況下,它展示了所有配置在?INSTALLED_APPS?中,已通過(guò)后臺(tái)應(yīng)用注冊(cè),按拼音排序的應(yīng)用。你可能想對(duì)這個(gè)頁(yè)面的布局做重大的修改。畢竟,索引頁(yè)是后臺(tái)的重要頁(yè)面,它應(yīng)該便于使用。

需要自定義的模板是?admin/index.html。(像上一節(jié)修改?admin/base_site.html?那樣修改此文件——從默認(rèn)目錄中拷貝此文件至自定義模板目錄)。打開此文件,你將看到它使用了一個(gè)叫做?app_list?的模板變量。這個(gè)變量包含了每個(gè)安裝的 Django 應(yīng)用。你可以用任何你期望的硬編碼鏈接(鏈接至特定對(duì)象的管理頁(yè))替代使用這個(gè)變量。

接下來(lái)要做什么??

初學(xué)者教程到這就結(jié)束了。隨后,你可能想閱讀?下一步看什么,看看下一步能做什么。

如果你很熟悉 Python 打包,且對(duì)學(xué)習(xí)如何把投票應(yīng)用改成“可復(fù)用應(yīng)用”感興趣,查看?進(jìn)階教程:如何創(chuàng)建可復(fù)用應(yīng)用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容