2 回答

TA貢獻1802條經驗 獲得超6個贊
根據我的評論,我認為除了實施完全定制的 CMS 之外,您無法實現您想要的一切 - 但如果您能夠改變 UI 和數據建模要求,那么 WagtailRoutablePageMixin是一種可能實現將文章作為單個單元進行編輯的一般模式,同時在前端將其呈現為多個頁面的方式。
在這種方法中,您將創建Article一個 Wagtail Page 模型,所有子頁面內容都定義為該模型上的字段(或 InlinePanel 子模型)。(如果您想在編輯界面中將內容條目拆分為選項卡,請參閱自定義選項卡式界面,盡管這不支持動態添加/重新排序它們。)然后您將為每個子頁面定義 URL 路由和模板文章:
from wagtail.core.models import Page
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
class ArticlePage(RoutablePageMixin, Page):
intro = StreamField(...)
main_page = StreamField(...)
conclusion = StreamField(...)
@route(r'^$')
def intro_view(self, request):
render(request, 'article/intro.html', {
'page': self,
})
@route(r'^main/$')
def main_page_view(self, request):
render(request, 'article/main_page.html', {
'page': self,
})
@route(r'^conclusion/$')
def conclusion_view(self, request):
render(request, 'article/conclusion.html', {
'page': self,
})
在此示例中,三個子頁面是硬編碼的,但通過更多工作(可能是帶有 slug 字段和 StreamField 的 InlinePanel 子模型),您可以使子頁面動態化。

TA貢獻1858條經驗 獲得超8個贊
我看到 gasman 已經為你的問題提供了答案,但我仍然要寫一個答案,原因有兩個:
我認為您需要更多關于為什么gasmans 的建議比您的建議更好的解決方案的指示,但在評論中寫下它的方式很多。
我之前已經實現了一個類似的解決方案,其中有一個類似“文章”的頂級對象,其中包含多個可重新排序的子對象,實際內容所在的位置。
為什么你應該創建Article
一個 Page 子類
您選擇不創建Article
的子類Page
,并且您說這是因為它Article
本身不包含任何內容,僅包含有關文章的元數據。這不是一個非常奇怪的思考過程,但我認為您正在查看Article
模型的錯誤要求。
讓我們看看 Wagtail 自己的Page
模型。它提供了哪些開箱即用的功能?
它提供了帶有父頁面和子頁面的樹結構,因此您的頁面可以放置在網站層次結構中的某個位置
它提供了一個
slug_field
, 以便 Wagtail 可以自動處理鏈接到您的頁面。它提供了起草、發布和取消發布的功能。
Wagtail 對內容沒有任何規定,讓您決定要放在Page
子類中的內容類型(如果有的話)。沒有正文的頁面示例如下:
聯系表格。
博客索引頁面。
在決定是否希望 aModel
成為 a 的子類時,您可以提出的好問題Page
是:
我希望這個對象有它自己的 url 嗎?
我是否希望能夠將此對象放置在我的網站層次結構中的某個位置?
我想對對象有 SEO 優勢嗎?
我是否希望能夠發布/取消發布此對象?
在您的情況下Article
,您幾乎可以對所有這些問題說“是”,因此將其設為Page
子類是明智的。這樣,您就不必重新發明輪子。
如何定義頁面的實際“正文”取決于您。您可以將實際內容放在該文章的片段或子頁面中?;蛘吣闵踔量梢赃x擇在你的模型中創建一個 StreamFields 列表。
如何實現有序子內容。
我以前實現過這樣的結構。我這樣做的方式與 gasman 的建議非常相似。
就我而言,我需要創建一個網站,您可以在其中找到一個對象(如您的文章)并為其顯示不同類型的解釋模塊。對于每個文檔,我創建了一個ArticlePage
,對于每個解釋模塊,我創建了一個名為ExplanationModule
.
然后,我創建了一個帶有排序的直通模型,并像 gasman 解釋的那樣在類中添加了一個 RoutablePageMixin。
結構看起來像這樣:
@register_snippet
class ArticlePageModule(models.Model):
...
title = models.CharField(max_length=100)
body = StreamField(LAYOUT_STREAMBLOCKS, null=True, blank=True)
panels = [
FieldPanel('title'),
StreamFieldPanel('body'),
]
class ArticlePageModulePlacement(Orderable, models.Model):
page = ParentalKey('articles.ArticlePage', on_delete=models.CASCADE, related_name='article_module_placements')
article_module = models.ForeignKey(ArticlePageModule, on_delete=models.CASCADE, related_name='+')
slug = models.SlugField()
panels = [
FieldPanel('slug'),
SnippetChooserPanel('article_module'),
]
class ArticlePage(Page, RoutablePageMixin):
# Metadata and other member values
....
content_panels = [
...
InlinePanel('article_module_placements', label="Modules"),
]
@route(r'^module/(?P<slug>[\w\-]+)/$')
def page_with_module(self, request, slug=None):
self.article_module_slug = slug
return self.serve(request)
def get_context(self, request):
context = super().get_context(request)
if hasattr(self, 'article_module_slug'):
context['ArticlePageModule'] = self.article_module_placements.filter(slug = self.article_module).first().article_module
return context
它的作用如下:
創建一個 ArticlePageModule 片段,它只是某種內容,例如標題和正文。
創建一個將 ArticlePage 鏈接到模塊的 ArticlePageModulePlacement,并添加以下內容:
蛞蝓
一個 Ordering(因為它是 Orderable 混合的子類)
創建一個做兩件事的 ArticlePage:
定義一個 ArticlePageModulePlacement 面板,它允許您添加 ArticlePageModulePlacements
子類 RoutablePagemixin,如 gasman 的回答中所述。
這為您提供了一種防鹡鸰、可重復使用且強大的方式來創建帶有子內容的文章。模塊不會顯示在選項卡中,但會顯示在名為“模塊”的面板下的頁面布局頁面上。
添加回答
舉報