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

Joa*_*iot 3 wagtail

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

\n

这是我发现的与此主题相关但不直接相关的内容\xe2\x80\x94

\n
    \n
  • Wagtail 文档:通过搜索“多对多”,唯一命中的是 taggit 模块上的部分(食谱页面)。

    \n
  • \n
  • Wagtail 文档:对 ParentalManyToManyField 的唯一参考是如何使用它在页面和类别之间创建 M2M 的演示(教程)

    \n
  • \n
  • 这篇 2015 年关于 Wagtail 中 M2M 关系的文章(它在一个 SO“答案”中被引用,与我在这里提出的问题基本相同)。尽管它没有讨论页面与页面的关系,但所提出的方法可能适合工作。我修改后的模仿因各种错误而失败,具体取决于我尝试设置 InlinePanel 调用 \xe2\x80\x94 的方式,但帖子中的示例代码以同样的方式失败,因此要么没有经过测试,要么它\' s 在 2.x 中已过时。

    \n
  • \n
\n
    class PersonPage(Page):\n        pass\n    \n    PersonPage.content_panels =  [\n        InlinePanel(\'ps_links\', label=\'PS Links\'), \n    ]   \n    \n    class PersonSitePageLink():\n        spage = models.ForeignKey(\'SitePage\', on_delete=models.SET_NULL, related_name=\'sites\')\n        ppage = ParentalKey(\'PersonPage\', related_name=\'ps_links\', on_delete=models.SET_NULL,)\n        panels = [\n            FieldPanel(\'spage\')\n        ]\n\n    class SitePage(Page):\n        pass\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 这种技术对于将页面模型与其自身相关联效果很好,但是将其扩展为包含两个不同的模型会创建两组平行但不相连的关系(您可以选择任意 Bug 页面链接到任何 Plant 页面,反之亦然,但是您的 Plants编辑 Bug 时选择的不显示)。我想我在代码中明白了原因,但我没有看到如何在两个页面之间建立单个 M2M 连接。
  • \n
\n
    class PlantPage(Page):\n        related_bugs = ParentalManyToManyField(\'BugPage\', blank=True)\n        content_panels = Page.content_panels + [\n            FieldPanel(\'related_bugs\'),\n        ]   \n\n    class BugPage(Page):\n        related_plants = ParentalManyToManyField(\'PlantPage\', blank=True)\n        content_panels = Page.content_panels + [\n            FieldPanel(\'related_plants\'),\n        ]   \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 这一篇也只讨论页面内模型(而不是页面间模型)M2M。(它是 ParentalManyToManyField 之前的版本,实际上只能从 Wayback Machine 获得。)
  • \n
\n

LB *_*ton 5

我希望这会有所帮助,我从这篇关于从AccordBox 文章ParentalManyToManyField中转向“链接”每个页面的中心模型的文章中获得了灵感。

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

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

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

概述

  • 创建一个新的“关系”来扩展models.Model这将是这两个页面模型之间的关系。
  • 这个新模型中的每个字段将是通过模型集群的两种页面类型,ParentalKey每个类型都有一个逻辑related_name集,该逻辑集是关系的另一端。
  • 无需在此模型上进行设置,因为我们将通过kwargpanels单独声明面板- 请参阅InlinePanel 文档panelsInlinePanel
  • 最后,每个人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')]),
    ]
Run Code Online (Sandbox Code Playgroud)

进一步阅读