亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Wagtail 中實現文章和頁面模型之間的一對多

在 Wagtail 中實現文章和頁面模型之間的一對多

jeck貓 2022-06-14 09:51:16
我正在嘗試使用文章到頁面結構設置 Wagtail 網站,但我正在努力。例如,一篇評論文章可能有一個介紹頁面、一個基準頁面和一個結論頁面。我想弄清楚如何在 wagtail 中允許這種關系并擁有它,以便編輯可以將多個頁面添加到同一頁面上的同一篇文章中。我可以想象頁面界面看起來有點像你在頁面上的內容、推廣和設置,但具有添加、重命名和重新排序頁面的能力。我嘗試在鏈接到文章的頁面模型上使用外鍵,但我無法以我想要的方式在管理員中顯示它。這是我想要使用的模型布局的 django 版本。您有一篇由一頁或多頁組成的父文章。這些頁面應該是可編輯的、可排序的,并且可以在管理員的一個面板中使用流域創建:Class Article(models.Model)    STATE_DRAFT = 0    STATE_REVIEW= 1    STATE_PUBLICATION = 2    STATE_HIDDEN = 3    STATE = (        (STATE_DRAFT, 'draft'),        (STATE_REVIEW, 'pending review'),        (STATE_PUBLICATION, 'ready for publication'),        (STATE_HIDDEN, 'hide and ignore'),    )    title = models.CharField(_('title'), max_length=256)    slug = models.SlugField(        _('slug'), unique=True, blank=True, default='', max_length=256    )    description = models.TextField(        _('description'), max_length=256, blank=True, default=''    )    author = models.ForeignKey(        User, on_delete=models.CASCADE, related_name='article'    )    publication = models.DateTimeField(        null=True, blank=True, default=None, db_index=True, help_text='''            What date and time should the article get published        '''    )    state = models.PositiveIntegerField(        default=0, choices=STATE, help_text='What stage is the article at?'    )    featured = models.BooleanField(        default=False,        help_text='Whether or not the article should get featured'    )class Page(Page):    article = models.ForeignKey(        'Article', on_delete=models.CASCADE, related_name='pages'    )    title = models.CharField(max_length=256)    number = models.PositiveIntegerField(default=1) # So pages are ordered    body = models.TextField(blank=True)
查看完整描述

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 子模型),您可以使子頁面動態化。


查看完整回答
反對 回復 2022-06-14
?
猛跑小豬

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 的回答中所述。

這為您提供了一種防鹡鸰、可重復使用且強大的方式來創建帶有子內容的文章。模塊不會顯示在選項卡中,但會顯示在名為“模塊”的面板下的頁面布局頁面上。


查看完整回答
反對 回復 2022-06-14
  • 2 回答
  • 0 關注
  • 174 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號