要檢查您是否有合適的 Python 3 版本:

如果這不返回版本號或返回低于 3.6 的版" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > Wagtail建站入門指南

Wagtail建站入門指南

時間:2023-07-11 04:54:02 | 來源:網(wǎng)站運(yùn)營

時間:2023-07-11 04:54:02 來源:網(wǎng)站運(yùn)營

Wagtail建站入門指南:

Wagtail建站入門指南

安裝并運(yùn)行 Wagtail ?[1]

安裝依賴項?[2]

Wagtail 支持 Python 3.6、3.7、3.8、3.9 和 3.10。

要檢查您是否有合適的 Python 3 版本:

如果這不返回版本號或返回低于 3.6 的版本,則需要安裝 Python 3。

重要的

在安裝 Wagtail 之前,需要安裝libjpegzlib庫,它們支持處理 JPEG、PNG 和 GIF 圖像(通過 Python Pillow庫)。執(zhí)行此操作的方法因平臺而異 - 請參閱 Pillow 特定于平臺的安裝說明。

創(chuàng)建并激活虛擬環(huán)境?[3]

我們建議使用虛擬環(huán)境,它將已安裝的依賴項與其他項目隔離開來。本教程使用venv,它與 Python 3 一起打包。

在 Windows (cmd.exe) 上:

$ python3 -m venv mysiteenv$ mysite/env/Scripts/activate.bat在 GNU/Linux 或 MacOS (bash) 上:

$ python3 -m venv mysite/env$ source mysite/env/bin/activate**對于其他 shell,**請參閱ref="https://docs.python.org/3/library/venv.html">venv文檔。

筆記

如果您使用版本控制(例如 git),mysite將是您項目的目錄。env它里面的目錄應(yīng)該從任何版本控制中排除。

安裝 Wagtail ?[4]

使用Python自帶的pip安裝Wagtail及其依賴:

生成您的站點?[5]

Wagtail 提供了一個start類似于. 在您的項目中運(yùn)行將生成一個新文件夾,其中包含一些特定于 Wagtail 的附加功能,包括所需的項目設(shè)置、一個帶有空白模型和基本模板的“home”應(yīng)用程序,以及一個示例“搜索”應(yīng)用程序。django-admin startproject``wagtail start mysite``mysite``HomePage

由于該文件夾mysite已由 創(chuàng)建venv,請使用附加參數(shù)運(yùn)行以指定目標(biāo)目錄:wagtail start

$ wagtail start mysite mysite

筆記

通常,在 Wagtail 中,每個頁面類型或內(nèi)容類型由單個應(yīng)用程序表示。但是,不同的應(yīng)用程序可以相互了解并訪問彼此的數(shù)據(jù)。所有應(yīng)用程序都需要INSTALLED_APPSsettings文件部分注冊。查看此文件以了解start命令如何在其中列出它們。

安裝項目依賴項?[6]

cd mysite pip install -r requirements.txt

這確保您擁有相關(guān)版本的 Wagtail、Django 以及您剛剛創(chuàng)建的項目的任何其他依賴項。

創(chuàng)建數(shù)據(jù)庫?[7]

如果您尚未更新項目設(shè)置,這將是項目目錄中的 SQLite 數(shù)據(jù)庫文件。

$ python manage.py migrate

此命令可確保數(shù)據(jù)庫中的表與項目中的模型匹配。每次更改模型時(例如,您可以向模型添加字段),您都需要運(yùn)行此命令以更新數(shù)據(jù)庫。

創(chuàng)建管理員用戶?[8]

$ python manage.py createsuperuser

當(dāng)?shù)卿浀焦芾碚军c時,超級用戶具有完全權(quán)限并且能夠查看/創(chuàng)建/管理數(shù)據(jù)庫。

擴(kuò)展主頁模型?[9]

開箱即用,“home”應(yīng)用程序在 中定義了一個空白HomePage模型models.py,以及創(chuàng)建主頁并配置 Wagtail 以使用它的遷移。

編輯home/models.py如下,向body模型添加一個字段:

from django.db import modelsfrom wagtail.core.models import Pagefrom wagtail.core.fields import RichTextFieldfrom wagtail.admin.edit_handlers import FieldPanelclass HomePage(Page): body = RichTextField(blank=True) content_panels = Page.content_panels + [ FieldPanel('body', classname="full"), ]body被定義為RichTextField,一個特殊的 Wagtail 字段。當(dāng) 時blank=True,表示該字段不是必需的,可以為空。您可以使用任何Django 核心字段。content_panels定義編輯界面的功能和布局。向 中添加字段時content_panels,可以在 Wagtail 界面上對其進(jìn)行編輯。有關(guān)創(chuàng)建頁面模型的更多信息。

運(yùn)行(這將創(chuàng)建遷移文件),然后 (這將執(zhí)行遷移并使用您的模型更改更新數(shù)據(jù)庫)。每次更改模型定義時都必須運(yùn)行上述命令。python manage.py makemigrations``python manage.py migrate

您現(xiàn)在可以在 Wagtail 管理區(qū)域內(nèi)編輯主頁(轉(zhuǎn)到頁面、主頁,然后編輯)以查看新的正文字段。在正文字段中輸入一些文本,然后通過選擇頁面編輯器底部的_Publish_而不是_Save Draft_來_發(fā)布_頁面。

現(xiàn)在需要更新頁面模板以反映對模型所做的更改。Wagtail 使用普通的 Django 模板來呈現(xiàn)每種頁面類型。默認(rèn)情況下,它將查找由應(yīng)用程序和模型名稱組成的模板文件名,用下劃線分隔大寫字母(例如,“home”應(yīng)用程序中的 HomePage 變?yōu)?home/home_page.html)。這個模板文件可以存在于Django 模板規(guī)則識別的任何位置 ;通常它被放置在templates應(yīng)用程序內(nèi)的文件夾下。

編輯home/templates/home/home_page.html以包含以下內(nèi)容:

{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-homepage{% endblock %}{% block content %} {{ page.body|richtext }}{% endblock %}base.html引用父模板并且必須始終是模板中使用的第一個模板標(biāo)記。從此模板擴(kuò)展可以避免重寫代碼,并允許應(yīng)用程序中的頁面共享相似的框架(通過在子模板中使用塊標(biāo)記,您可以覆蓋父模板中的特定內(nèi)容)。

wagtailcore_tags 還必須在模板頂部加載,并為 Django 提供的標(biāo)簽提供額外的標(biāo)簽。

一個基本的博客?[10]

我們現(xiàn)在準(zhǔn)備創(chuàng)建一個博客。為此,請運(yùn)行 以在您的 Wagtail 站點中創(chuàng)建一個新應(yīng)用程序。python manage.py startapp blog

新添加blog的應(yīng)用程序,以INSTALLED_APPSmysite/settings/base.py。

博客索引和帖子?[11]

讓我們從一個簡單的博客索引頁開始。在blog/models.py

from wagtail.core.models import Pagefrom wagtail.core.fields import RichTextFieldfrom wagtail.admin.edit_handlers import FieldPanelclass BlogIndexPage(Page): intro = RichTextField(blank=True) content_panels = Page.content_panels + [ FieldPanel('intro', classname="full") ]運(yùn)行和。python manage.py makemigrations``python manage.py migrate

由于模型被調(diào)用BlogIndexPage,默認(rèn)模板名稱(除非我們覆蓋它)將是blog/templates/blog/blog_index_page.html. 使用以下內(nèi)容創(chuàng)建此文件:

{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-blogindexpage{% endblock %}{% block content %} <h1>{{ page.title }}</h1> <div class="intro">{{ page.intro|richtext }}</div> {% for post in page.get_children %} <h2><a href="{% pageurl post %}">{{ post.title }}</a></h2> {{ post.specific.intro }} {{ post.specific.body|richtext }} {% endfor %}{% endblock %}大部分內(nèi)容應(yīng)該很熟悉,但我們稍后會解釋get_children。請注意pageurl標(biāo)簽,它類似于 Django 的url標(biāo)簽,但采用 Wagtail Page 對象作為參數(shù)。

在 Wagtail 管理員中,創(chuàng)建一個BlogIndexPage作為主頁的子項,確保它在“推廣”選項卡上有“博客”,然后發(fā)布它。您現(xiàn)在應(yīng)該能夠訪問/blog您網(wǎng)站上的 url (注意“提升”選項卡中的 slug 如何定義頁面 URL)。

現(xiàn)在我們需要為我們的博客文章提供模型和模板。在blog/models.py

from django.db import modelsfrom wagtail.core.models import Pagefrom wagtail.core.fields import RichTextFieldfrom wagtail.admin.edit_handlers import FieldPanelfrom wagtail.search import index# Keep the definition of BlogIndexPage, and add:class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = RichTextField(blank=True) search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('date'), FieldPanel('intro'), FieldPanel('body', classname="full"), ]在上面的模型中,我們導(dǎo)入,index因為這使模型可搜索。然后,您可以列出您希望可供用戶搜索的字段。

運(yùn)行和。python manage.py makemigrations``python manage.py migrate

blog/templates/blog/blog_page.html以下位置創(chuàng)建模板:

{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-blogpage{% endblock %}{% block content %} <h1>{{ page.title }}</h1> <p class="meta">{{ page.date }}</p> <div class="intro">{{ page.intro }}</div> {{ page.body|richtext }} <p><a href="{{ page.get_parent.url }}">Return to blog</a></p>{% endblock %}請注意使用 Wagtail 的內(nèi)置get_parent()方法來獲取此帖子所屬博客的 URL。

現(xiàn)在創(chuàng)建一些博客文章作為BlogIndexPage. 創(chuàng)建帖子時,請務(wù)必選擇“博客頁面”類型。

Wagtail 使您可以完全控制在各種父內(nèi)容類型下可以創(chuàng)建哪些類型的內(nèi)容。默認(rèn)情況下,任何頁面類型都可以是任何其他頁面類型的子頁面。

完成編輯后發(fā)布每篇博文。

你現(xiàn)在應(yīng)該有一個工作博客的開始。訪問/blogURL,您應(yīng)該會看到如下內(nèi)容:

標(biāo)題應(yīng)該鏈接到帖子頁面,返回博客主頁的鏈接應(yīng)該出現(xiàn)在每個帖子頁面的頁腳中。

父母和孩子?[12]

您將在 Wagtail 中進(jìn)行的大部分工作都圍繞由節(jié)點和葉子組成的分層“樹”結(jié)構(gòu)的概念(請參閱理論)。在這種情況下,BlogIndexPage是一個“節(jié)點”,單個BlogPage實例是“葉子”。

再看看以下的膽量blog_index_page.html

{% for post in page.get_children %} <h2><a href="{% pageurl post %}">{{ post.title }}</a></h2> {{ post.specific.intro }} {{ post.specific.body|richtext }}{% endfor %}Wagtail 中的每個“頁面”都可以從其在層次結(jié)構(gòu)中的位置調(diào)用其父級或子級。但是為什么我們必須指定post.specific.intro而不是post.intro?這與我們定義模型的方式有關(guān):

class BlogPage(Page):

get_children()方法為我們獲取Page基類的實例列表。當(dāng)我們想要引用從基類繼承的實例的屬性時,Wagtail 提供了specific檢索實際BlogPage記錄的方法。雖然“title”字段存在于基本Page模型中,但“intro”只存在于BlogPage模型中,因此我們需要.specific訪問它。

為了收緊這樣的模板代碼,我們可以使用 Django 的with標(biāo)簽:

{% for post in page.get_children %} {% with post=post.specific %} <h2><a href="{% pageurl post %}">{{ post.title }}</a></h2> <p>{{ post.intro }}</p> {{ post.body|richtext }} {% endwith %}{% endfor %}當(dāng)您開始編寫更多定制的 Wagtail 代碼時,您會發(fā)現(xiàn)一整套 QuerySet 修飾符來幫助您導(dǎo)航層次結(jié)構(gòu)。

# Given a page object 'somepage':MyModel.objects.descendant_of(somepage)child_of(page) / not_child_of(somepage)ancestor_of(somepage) / not_ancestor_of(somepage)parent_of(somepage) / not_parent_of(somepage)sibling_of(somepage) / not_sibling_of(somepage)# ... and ...somepage.get_children()somepage.get_ancestors()somepage.get_descendants()somepage.get_siblings()更多信息請參見:頁面查詢集參考

覆蓋上下文?[13]

我們的博客索引視圖有幾個問題:

  1. 博客一般按時間_倒序_顯示內(nèi)容
  2. 我們要確保我們只顯示_已發(fā)布的_內(nèi)容。
為了完成這些事情,我們需要做的不僅僅是在模板中獲取索引頁面的子頁面。相反,我們希望修改模型定義中的 QuerySet。Wagtail 通過 overridableget_context()方法使這成為可能。BlogIndexPage 像這樣修改你的模型:

class BlogIndexPage(Page): intro = RichTextField(blank=True) def get_context(self, request): # Update context to include only published posts, ordered by reverse-chron context = super().get_context(request) blogpages = self.get_children().live().order_by('-first_published_at') context['blogpages'] = blogpages return context我們在這里所做的只是檢索原始上下文,創(chuàng)建自定義 QuerySet,將其添加到檢索到的上下文中,并將修改后的上下文返回給視圖。您還需要blog_index_page.html稍微修改模板。改變:

{% for post in page.get_children %}{% for post in blogpages %}

現(xiàn)在嘗試取消發(fā)布您的一篇文章 - 它應(yīng)該從博客索引頁面中消失。剩下的帖子現(xiàn)在應(yīng)該首先按照最近發(fā)布的帖子排序。

圖像?[14]

讓我們添加將圖片庫附加到我們的博客文章的功能。雖然可以簡單地將圖像插入body富文本字段,但將我們的畫廊圖像設(shè)置為數(shù)據(jù)庫中新的專用對象類型有幾個優(yōu)點 - 這樣,您可以完全控制圖像上的布局和樣式模板,而不必在富文本字段中以特定方式布置它們。它還使圖像可以在別處使用,獨立于博客文本 - 例如,在博客索引頁面上顯示縮略圖。

添加一個新BlogPageGalleryImage模型到models.py

from django.db import models# New imports added for ParentalKey, Orderable, InlinePanel, ImageChooserPanelfrom modelcluster.fields import ParentalKeyfrom wagtail.core.models import Page, Orderablefrom wagtail.core.fields import RichTextFieldfrom wagtail.admin.edit_handlers import FieldPanel, InlinePanelfrom wagtail.images.edit_handlers import ImageChooserPanelfrom wagtail.search import index# ... (Keep the definition of BlogIndexPage, and update BlogPage:)class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = RichTextField(blank=True) search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('date'), FieldPanel('intro'), FieldPanel('body', classname="full"), InlinePanel('gallery_images', label="Gallery images"), ]class BlogPageGalleryImage(Orderable): page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images') image = models.ForeignKey( 'wagtailimages.Image', on_delete=models.CASCADE, related_name='+' ) caption = models.CharField(blank=True, max_length=250) panels = [ ImageChooserPanel('image'), FieldPanel('caption'), ]運(yùn)行和。python manage.py makemigrations``python manage.py migrate

這里有一些新概念,所以讓我們一次一個:

繼承自向模型Orderable添加一個sort_order字段,以跟蹤圖庫中圖像的順序。

ParentalKeyBlogPage什么高度圖庫圖片到指定的頁面。A 的ParentalKey工作方式與 a 類似ForeignKey,但也定義BlogPageGalleryImageBlogPage模型的“子項” ,因此在提交審核和跟蹤修訂歷史等操作中,它被視為頁面的基本部分。

imageForeignKeyWagtail 的內(nèi)置Image模型,其中存儲了圖像本身。它帶有專用面板類型 ,ImageChooserPanel它提供了一個用于選擇現(xiàn)有圖像或上傳新圖像的彈出界面。這樣,我們允許一個圖像存在于多個畫廊中——實際上,我們在頁面和圖像之間創(chuàng)建了多對多關(guān)系。

on_delete=models.CASCADE在外鍵上指定意味著如果圖像從系統(tǒng)中刪除,圖庫條目也將被刪除。(在其他情況下,將條目留在原處可能是合適的 - 例如,如果“我們的員工”頁面包含有頭像的人的列表,并且其中一張照片被刪除,我們寧愿將該人留在放置在沒有照片的頁面上。在這種情況下,我們將外鍵設(shè)置為。)blank=True, null=True, on_delete=models.SET_NULL

最后,加入InlinePanelBlogPage.content_panels品牌的編輯界面上可用的畫廊圖像BlogPage。

調(diào)整您的博客頁面模板以包含圖像:

{% extends "base.html" %}{% load wagtailcore_tags wagtailimages_tags %}{% block body_class %}template-blogpage{% endblock %}{% block content %} <h1>{{ page.title }}</h1> <p class="meta">{{ page.date }}</p> <div class="intro">{{ page.intro }}</div> {{ page.body|richtext }} {% for item in page.gallery_images.all %} <div style="float: left; margin: 10px"> {% image item.image fill-320x240 %} <p>{{ item.caption }}</p> </div> {% endfor %} <p><a href="{{ page.get_parent.url }}">Return to blog</a></p>{% endblock %}這里我們使用標(biāo)簽(存在于庫中,在模板頂部導(dǎo)入)插入一個元素,帶有一個參數(shù)來指示應(yīng)該調(diào)整圖像大小和裁剪以填充 320x240 矩形。您可以在docs 中閱讀有關(guān)在模板中使用圖像的更多信息。{% image %}``wagtailimages_tags``<img>``fill-320x240

由于我們的圖庫圖像本身就是數(shù)據(jù)庫對象,因此我們現(xiàn)在可以獨立于博客文章正文查詢和重用它們。讓我們定義一個main_image方法,它從第一個畫廊項目(或者None如果不存在畫廊項目)返回圖像:

class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = RichTextField(blank=True) def main_image(self): gallery_item = self.gallery_images.first() if gallery_item: return gallery_item.image else: return None search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body'), ] content_panels = Page.content_panels + [ FieldPanel('date'), FieldPanel('intro'), FieldPanel('body', classname="full"), InlinePanel('gallery_images', label="Gallery images"), ]現(xiàn)在可以從我們的模板中使用此方法。更新blog_index_page.html以將主圖像作為縮略圖包含在每個帖子旁邊:

{% load wagtailcore_tags wagtailimages_tags %}{% for post in blogpages %} {% with post=post.specific %} <h2><a href="{% pageurl post %}">{{ post.title }}</a></h2> {% with post.main_image as main_image %} {% if main_image %}{% image main_image fill-160x100 %}{% endif %} {% endwith %} <p>{{ post.intro }}</p> {{ post.body|richtext }} {% endwith %}{% endfor %}

標(biāo)記帖子?[15]

假設(shè)我們想讓編輯“標(biāo)記”他們的帖子,這樣讀者就可以,例如,一起查看所有與自行車相關(guān)的內(nèi)容。為此,我們需要調(diào)用與 Wagtail 捆綁在一起的標(biāo)記系統(tǒng),將其附加到BlogPage 模型和內(nèi)容面板,并在博客帖子模板上呈現(xiàn)鏈接標(biāo)簽。當(dāng)然,我們還需要一個工作標(biāo)簽特定的 URL 視圖。

首先,models.py再次修改:

from django.db import models# New imports added for ClusterTaggableManager, TaggedItemBase, MultiFieldPanelfrom modelcluster.fields import ParentalKeyfrom modelcluster.contrib.taggit import ClusterTaggableManagerfrom taggit.models import TaggedItemBasefrom wagtail.core.models import Page, Orderablefrom wagtail.core.fields import RichTextFieldfrom wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanelfrom wagtail.images.edit_handlers import ImageChooserPanelfrom wagtail.search import index# ... (Keep the definition of BlogIndexPage)class BlogPageTag(TaggedItemBase): content_object = ParentalKey( 'BlogPage', related_name='tagged_items', on_delete=models.CASCADE )class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = RichTextField(blank=True) tags = ClusterTaggableManager(through=BlogPageTag, blank=True) # ... (Keep the main_image method and search_fields definition) content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('date'), FieldPanel('tags'), ], heading="Blog information"), FieldPanel('intro'), FieldPanel('body'), InlinePanel('gallery_images', label="Gallery images"), ]運(yùn)行和。python manage.py makemigrations``python manage.py migrate

請注意新的modelclustertaggit進(jìn)口的、新 BlogPageTag模型的添加以及 上的tags字段的添加BlogPage。我們還借此機(jī)會使用MultiFieldPanelincontent_panels 將日期和標(biāo)簽字段組合在一起以提高可讀性。

編輯您的BlogPage實例之一,您現(xiàn)在應(yīng)該能夠標(biāo)記帖子:

要在 上呈現(xiàn)標(biāo)簽BlogPage,請將其添加到blog_page.html

{% if page.tags.all.count %} <div class="tags"> <h3>Tags</h3> {% for tag in page.tags.all %} <a href="{% slugurl 'tags' %}?tag={{ tag }}"><button type="button">{{ tag }}</button></a> {% endfor %} </div>{% endif %}請注意,我們使用內(nèi)置slugurl 標(biāo)記而不是pageurl我們之前使用的鏈接到此處的頁面。不同之處在于slugurl它以 Page slug(來自“提升”選項卡)作為參數(shù)。pageurl更常用,因為它是明確的并且避免了額外的數(shù)據(jù)庫查找。但是在這個循環(huán)的情況下,Page 對象不是隨時可用的,所以我們回到不太喜歡的slugurl標(biāo)簽。

訪問帶有標(biāo)簽的博客文章現(xiàn)在應(yīng)該在底部顯示一組鏈接按鈕 - 每個標(biāo)簽一個。但是,單擊按鈕會得到 404,因為我們還沒有定義“標(biāo)簽”視圖。添加到models.py

class BlogTagIndexPage(Page): def get_context(self, request): # Filter by tag tag = request.GET.get('tag') blogpages = BlogPage.objects.filter(tags__name=tag) # Update template context context = super().get_context(request) context['blogpages'] = blogpages return context請注意,這個基于頁面的模型沒有定義自己的字段。即使沒有字段,子類化Page也使它成為 Wagtail 生態(tài)系統(tǒng)的一部分,這樣你就可以在管理中給它一個標(biāo)題和 URL,這樣你就可以通過從它的get_context()方法返回一個 QuerySet 來操縱它的內(nèi)容。

將其遷移進(jìn)來,然后BlogTagIndexPage在管理員中創(chuàng)建一個新的。您可能希望將新頁面/視圖創(chuàng)建為 Homepage 的子項,與您的博客索引平行。在“提升”選項卡上為其添加 slug“標(biāo)簽”。

Access/tags和 Django 會告訴你你可能已經(jīng)知道的事情:你需要創(chuàng)建一個模板blog/blog_tag_index_page.html

{% extends "base.html" %}{% load wagtailcore_tags %}{% block content %} {% if request.GET.tag %} <h4>Showing pages tagged "{{ request.GET.tag }}"</h4> {% endif %} {% for blogpage in blogpages %} <p> <strong><a href="{% pageurl blogpage %}">{{ blogpage.title }}</a></strong><br /> <small>Revised: {{ blogpage.latest_revision_created_at }}</small><br /> {% if blogpage.author %} <p>By {{ blogpage.author.profile }}</p> {% endif %} </p> {% empty %} No pages found with that tag. {% endfor %}{% endblock %}我們正在調(diào)用 模型latest_revision_created_at上的內(nèi)置字段Page- 知道這總是可用的很方便。

我們還沒有在我們的BlogPage模型中添加一個“作者”字段,我們也沒有作者的 Profile 模型——我們將這些留給讀者作為練習(xí)。

單擊博客帖子底部的標(biāo)簽按鈕現(xiàn)在應(yīng)該呈現(xiàn)如下頁面:

類別?[16]

讓我們?yōu)槲覀兊牟┛吞砑右粋€類別系統(tǒng)。與標(biāo)簽不同,頁面作者只需在頁面上使用標(biāo)簽即可將標(biāo)簽引入,我們的類別將是一個固定列表,由站點所有者通過管理界面的單獨區(qū)域進(jìn)行管理。

首先,我們定義一個BlogCategory模型。類別本身并不是一個頁面,因此我們將其定義為標(biāo)準(zhǔn)的 Django,models.Model而不是從Page. Wagtail 為需要通過管理界面管理但不作為頁面樹本身的一部分存在的可重用內(nèi)容片段引入了“片段”的概念;可以通過添加@register_snippet裝飾器將模型注冊為片段。到目前為止,我們在頁面上使用的所有字段類型也可以用于片段 - 在這里,我們將為每個類別提供一個圖標(biāo)圖像和一個名稱。添加到blog/models.py

from wagtail.snippets.models import register_snippet@register_snippetclass BlogCategory(models.Model): name = models.CharField(max_length=255) icon = models.ForeignKey( 'wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) panels = [ FieldPanel('name'), ImageChooserPanel('icon'), ] def __str__(self): return self.name class Meta: verbose_name_plural = 'blog categories'請注意,我們正在使用panels而不是content_panels在這里 - 由于片段通常不需要諸如 slug 或發(fā)布日期之類的字段,因此它們的編輯界面不會作為標(biāo)準(zhǔn)拆分為單獨的“內(nèi)容”/“推廣”/“設(shè)置”選項卡,并且因此無需區(qū)分“內(nèi)容面板”和“推廣面板”。

遷移此更改,并通過現(xiàn)在顯示在管理菜單中的代碼段區(qū)域創(chuàng)建一些類別。

我們現(xiàn)在可以向BlogPage模型添加類別,作為多對多字段。我們?yōu)榇耸褂玫淖侄晤愋褪?code>ParentalManyToManyField- 這是標(biāo)準(zhǔn) Django 的變體,ManyToManyField它確保所選對象正確存儲在修訂歷史記錄中的頁面記錄中,與ParentalKey替換ForeignKey一對多關(guān)系的方式大致相同。

# New imports added for forms and ParentalManyToManyFieldfrom django import formsfrom django.db import modelsfrom modelcluster.fields import ParentalKey, ParentalManyToManyFieldfrom modelcluster.contrib.taggit import ClusterTaggableManagerfrom taggit.models import TaggedItemBase# ...class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = RichTextField(blank=True) tags = ClusterTaggableManager(through=BlogPageTag, blank=True) categories = ParentalManyToManyField('blog.BlogCategory', blank=True) # ... (Keep the main_image method and search_fields definition) content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('date'), FieldPanel('tags'), FieldPanel('categories', widget=forms.CheckboxSelectMultiple), ], heading="Blog information"), FieldPanel('intro'), FieldPanel('body'), InlinePanel('gallery_images', label="Gallery images"), ]在這里,我們使用定義中的widget關(guān)鍵字參數(shù)FieldPanel來指定基于復(fù)選框的小部件而不是默認(rèn)的多選框,因為這通常被認(rèn)為對用戶更友好。

最后,我們可以更新blog_page.html模板以顯示類別:

<h1>{{ page.title }}</h1><p class="meta">{{ page.date }}</p>{% with categories=page.categories.all %} {% if categories %} <h3>Posted in:</h3> <ul> {% for category in categories %} <li style="display: inline"> {% image category.icon fill-32x32 style="vertical-align: middle" %} {{ category.name }} </li> {% endfor %} </ul> {% endif %}{% endwith %}

參考資料

[1]

固定鏈接到這個標(biāo)題: #install-and-run-wagtail

[2]

固定鏈接到這個標(biāo)題: #install-dependencies

[3]

固定鏈接到這個標(biāo)題: #create-and-activate-a-virtual-environment

[4]

固定鏈接到這個標(biāo)題: #install-wagtail

[5]

固定鏈接到這個標(biāo)題: #generate-your-site

[6]

固定鏈接到這個標(biāo)題: #install-project-dependencies

[7]

固定鏈接到這個標(biāo)題: #create-the-database

[8]

固定鏈接到這個標(biāo)題: #create-an-admin-user

[9]

固定鏈接到這個標(biāo)題: #extend-the-homepage-model

[10]

固定鏈接到這個標(biāo)題: #a-basic-blog

[11]

固定鏈接到這個標(biāo)題: #blog-index-and-posts

[12]

固定鏈接到這個標(biāo)題: #parents-and-children

[13]

固定鏈接到這個標(biāo)題: #overriding-context

[14]

固定鏈接到這個標(biāo)題: #images

[15]

固定鏈接到這個標(biāo)題: #tagging-posts

[16]

固定鏈接到這個標(biāo)題: #categories

關(guān)鍵詞:指南,入門

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉