不同页面模型之间的 Wagtail 多对多链接

Wagtail many-to-many links between different Page models

有没有人知道或知道在不同页面模型之间建立多对多关系的秘诀(示例代码 and/or 说明)?如果我有 PersonPage 和 SitePage 模型,如何连接页面(一个人可以在多个站点工作,一个站点可以有多个人在那里工作)?

这是我发现的与该主题相关但不直接相关的内容—

    class PersonPage(Page):
        pass
    
    PersonPage.content_panels =  [
        InlinePanel('ps_links', label='PS Links'), 
    ]   
    
    class PersonSitePageLink():
        spage = models.ForeignKey('SitePage', on_delete=models.SET_NULL, related_name='sites')
        ppage = ParentalKey('PersonPage', related_name='ps_links', on_delete=models.SET_NULL,)
        panels = [
            FieldPanel('spage')
        ]

    class SitePage(Page):
        pass
    class PlantPage(Page):
        related_bugs = ParentalManyToManyField('BugPage', blank=True)
        content_panels = Page.content_panels + [
            FieldPanel('related_bugs'),
        ]   

    class BugPage(Page):
        related_plants = ParentalManyToManyField('PlantPage', blank=True)
        content_panels = Page.content_panels + [
            FieldPanel('related_plants'),
        ]   

我希望这会有所帮助,我从这篇关于从 ParentalManyToManyField 移动到中心模型的文章中获得灵感,该模型 'links' 每个页面都来自此 AccordBox article

事实证明 InlinePanel 并不完全支持 ParentalManyToManyField,因此您遇到的问题 运行。

我能够针对您上面的选项实施一种改进的方法,它应该可以解决您的问题。

提醒所有 Page 个模型已经扩展 ClusterableModel,因此无需将其添加到您创建的任何模型中。

概览

  • 创建一个扩展 models.Model 的新 'relation',这将是这两个页面模型之间的关系。
  • 这个新模型中的每个字段都是通过模型集群 ParentalKey 的两种页面类型,每种类型都有一个逻辑 related_name 集,即关系的另一端。
  • 无需在此模型上设置 panels,因为我们将通过 panels kwarg 将面板单独声明为 InlinePanel - 请参阅 InlinePanel docs.
  • 最后,每个人 Pagecontent_panels 添加了一个 InlinePanel,它通过该模型的 related_name 间接引用中心关系模型,添加另一边参考 PageChooserPanel.

示例代码


from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, PageChooserPanel

class PersonPageSitePageRelation(models.Model):
    person = ParentalKey('app.PersonPage', on_delete=models.CASCADE, related_name='sites')
    site = ParentalKey('app.SitePage', on_delete=models.CASCADE, related_name='people')
    # Optional: some additional fields (e.g. 'note') for this relation
    # Important: NOT setting any `panels` here, will be set individually for each 'direction'

    class Meta:
        unique_together = ('person', 'site')


class PersonPage(Page):
    # ... fields (note: `sites` does NOT need to be declared as a field)
    
    # Now we add an `InlinePanel` that will connect to the parental connection to PersonPageSitePageRelation via the related name `sites`, but the panels available will be the PersonPageSitePageRelation's field `site`
    content_panels = Page.content_panels + [
        # ... other FieldPanel etc
        InlinePanel('sites', label='Related Sites', [PageChooserPanel('site')]),
    ]


class SitePage(Page):
    # ... fields (note: `people` does NOT need to be declared as a field)

    # Now we add an `InlinePanel` that will connect to the parental connection to PersonPageSitePageRelation via the related name `people`, but the panels available will be the PersonPageSitePageRelation's field `person`
    content_panels = Page.content_panels + [
        # ... other FieldPanel etc
        InlinePanel('people', label='Related People', panels=[PageChooserPanel('person')]),
    ]

进一步阅读