电竞比分网-中国电竞赛事及体育赛事平台

分享

編寫你的第一個 Django 應(yīng)用,第 7 部分 | Django 文檔 | Django

 寧靜致遠(yuǎn)oj1kn5 2019-06-13

編寫你的第一個 Django 應(yīng)用,第 7 部分?

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

自定義后臺表單?

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

讓我們通過重排列表單上的字段來看看它是怎么工作的。用以下內(nèi)容替換 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)

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

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

Fields have been reordered

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

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

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

Form has fieldsets now

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

好了,現(xiàn)在我們有了投票的后臺頁。不過,一個 Question 有多個 Choice,但后臺頁卻沒有顯示多個選項。

好了。

有兩個方法可以解決這個問題。第一個就是仿照我們向后臺注冊 Question 一樣注冊 Choice 。這很簡單:

polls/admin.py?
from django.contrib import admin

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

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

Choice admin page

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

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

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

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

polls/admin.py?
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 后臺頁面編輯。默認(rèn)提供 3 個足夠的選項字段。”

加載“添加投票”頁面來看看它長啥樣:

Add question page now has choices on it

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

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

Additional slot added dynamically

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

polls/admin.py?
class ChoiceInline(admin.TabularInline):
    #...

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

Add question page now has more compact choices

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

自定義后臺更改列表?

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

以下是它此時的外觀:

Polls change list page

默認(rèn)情況下,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')

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

Polls change list page, updated

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

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

polls/models.py?
class Question(models.Model):
    # ...
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now
    was_published_recently.admin_order_field = 'pub_date'
    was_published_recently.boolean = True
    was_published_recently.short_description = 'Published recently?'

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

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

list_filter = ['pub_date']

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

Polls change list page, updated

展示的過濾器類型取決你你要過濾的字段的類型。因為 pub_date 是類 DateTimeField,Django 知道要提供哪個過濾器:“任意時間”,“今天”,“過去7天”,“這個月”和“今年”。

這已經(jīng)弄的很好了。讓我們再擴充些功能:

search_fields = ['question_text']

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

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

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

在每個后臺頁頂部顯示“Django 管理員”顯得很滑稽。這只是一串占位文本。

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

自定義你的 工程的 模板?

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

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

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

組織模板

就像靜態(tài)文件一樣,我們 可以 把所有的模板文件放在一個大模板目錄內(nèi),這樣它也能工作的很好。但是,屬于特定應(yīng)用的模板文件最好放在應(yīng)用所屬的模板目錄(例如 polls/templates),而不是工程的模板目錄(templates)。我們會在 創(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ù)制到這個目錄內(nèi)。

Django 的源文件在哪里?

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

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

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

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

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

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

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

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

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

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

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

自定義后臺主頁?

在類似的說明中,你可能想要自定義 Django 后臺索引頁的外觀。

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

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

接下來要做什么??

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

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

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多