簡體   English   中英

用於自引用多對多關系的 Wagtail 面板 model

[英]Wagtail panel for self-referential many to many relationships with a through model

我正忙着在 wagtail 中制作類似知識圖譜的東西。

CurriculumContentItem是該圖上的一個節點。 它和自己是多對多的關系,通過model有重要字段。

我正在努力讓它在管理頁面中可用。 請參閱內聯評論:

class ContentItemOrder(models.Model):
    post = models.ForeignKey(
        "CurriculumContentItem", on_delete=models.PROTECT, related_name="pre_ordered_content"
    )
    pre = models.ForeignKey(
        "CurriculumContentItem", on_delete=models.PROTECT, related_name="post_ordered_content"
    )
    hard_requirement = models.BooleanField(default=True)

class CurriculumContentItem(Page):
    body = RichTextField(blank=True)

    prerequisites = models.ManyToManyField(
        "CurriculumContentItem",
        related_name="unlocks",
        through="ContentItemOrder",
        symmetrical=False,
    )

    content_panels = Page.content_panels + [
        # FieldPanel("prerequisites") 
        # FieldPanel just lets me select CurriculumContentItems, but I need to access fields in the through model

        # InlinePanel("prerequisites"), 
        # This causes a recursion error

        FieldPanel('body', classname="full collapsible"),
    ]

如果我想在正常的 Django 管理員中執行此操作,我將使用內聯來指定先決條件。 就像是:

class ContentItemOrderPostAdmin(admin.TabularInline):
    model = models.ContentItem.prerequisites.through
    fk_name = "post"

class ContentItemOrderPreAdmin(admin.TabularInline):
    model = models.ContentItem.unlocks.through
    fk_name = "pre"

Wagtail中有類似的機制嗎?

看來我需要為此創建一個自定義面板。

我建議構建一個 InlinePanel 指向您的“通過”model,這意味着您正在處理一對多關系而不是多對多關系:

class ContentItemOrder(models.Model):
    post = ParentalKey(
        "CurriculumContentItem", related_name="pre_ordered_content"
    )
    pre = models.ForeignKey(
        "CurriculumContentItem", on_delete=models.PROTECT, related_name="post_ordered_content"
    )
    hard_requirement = models.BooleanField(default=True)

    panels = [
        PageChooserPanel('pre'),
        FieldPanel('hard_requirement')
    ]


class CurriculumContentItem(Page):
    body = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        InlinePanel("pre_ordered_content"), 

        FieldPanel('body', classname="full collapsible"),
    ]

這有效:

  1. 通過 model 繼承自 Orderable
  2. 使用ParentalKey而不是ForeignKey
  3. 使用 InlinePanel 引用直通模型中字段的相關名稱
from modelcluster.fields import ParentalKey
from wagtail.core.models import Page, Orderable


class ContentItemOrder(Orderable):   ### 1
    post = ParentalKey(   ### 2
        "CurriculumContentItem", on_delete=models.PROTECT, related_name="pre_ordered_content"
    )
    pre = ParentalKey(   ### 2
        "CurriculumContentItem", on_delete=models.PROTECT, related_name="post_ordered_content"
    )
    hard_requirement = models.BooleanField(default=True)

    panels = [
        PageChooserPanel('pre'),
        PageChooserPanel('post'),
        FieldPanel('hard_requirement'),
    ]


class CurriculumContentItem(Page):
    body = RichTextField(blank=True)

    prerequisites = models.ManyToManyField(
        "CurriculumContentItem",
        related_name="unlocks",
        through="ContentItemOrder",
        symmetrical=False,
    )

    content_panels = Page.content_panels + [
        InlinePanel('pre_ordered_content', label="prerequisites"),  ### 3
        InlinePanel('post_ordered_content', label="unlocks"),       ### 3

        FieldPanel('body', classname="full collapsible"),
    ]

我擔心每個內聯會有 2 個可用的 PageChooser 字段,但 wagtail 足夠聰明(而且神奇),它只繪制我們需要的那個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM