Wagtail:一页上的多个可重用元素

Wagtail: Multiple reusable elements on one Page

我需要创建一个可重复使用的元素(cta 按钮),我可以将其包含在整个页面的许多地方。

这些 cta 按钮在整个设计中使用了约 8 次。如果不复制粘贴怎么办?

与此类似:Ways to create reusable sets of fields in Wagtail?除了我必须能够在一个页面上多次使用该集。

这就是我想要做的:

class HomePage(Page):
    
    template = "home/home_page.html"

    hero_heading = models.CharField(max_length=50)
    hero_subheading = models.CharField(max_length=255)


    hero_cta1 = HeroCTA1() # abstract reusable model
    hero_cta2 = HeroCTA2()

    content_panels = Page.content_panels + [
        FieldPanel("hero_heading"),
        FieldPanel("hero_subheading"),
        hero_cta1.panels,
        hero_cta2.panels,
    ]

我对可重用 CTAButton 的尝试class:

class CTAButton(models.Model):
    text = RichTextField(max_length=25, features=["bold"])
    url = models.URLField(null=True, blank=True)
    page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="%(app_label)s_%(class)s_page",
    )

    panels = MultiFieldPanel(
            [
                FieldPanel("text"),
                FieldPanel("url"),
                PageChooserPanel("page"),
            ],
            heading="CTA Button Fields",
            classname="collapsible",
        )

    class Meta:
        abstract = True


class HeroCTA1(CTAButton):
    pass

class HeroCTA2(CTAButton):
    pass

除非这不起作用:/ 我遇到“主页没有名为 'page' 的字段”

不应该在 'text' 中断,因为它在 'page' 之前吗?

关于如何进行的任何建议?

查看模型继承的 django 文档 您可以通过三种方法在 django 中实现模型继承 wagtail 是由 djanog 制作的,因此您也可以在其中使用抽象模型继承以获取更多信息,请查看此文档 https://docs.djangoproject.com/en/3.0/topics/db/models/#model-inheritance

如果您的页面设计有 8 个位置可以放置 CTA 按钮,那么将其视为灵活的元素序列可能更有用,在这些元素中,CTA 按钮可以自由地与页面选择的其他类型的内容混合在一起作者,而不是在特定点具有特定元素的固定布局。 Wagtail 的 StreamField 提供了这种灵活的布局:https://docs.wagtail.io/en/stable/topics/streamfield.html

我听从了@gasman 的建议,将模板分解成块,并使用 mixin 使其保持干爽。

此解决方案提取了 href 函数并允许它在多个 CTA 块中使用,但它对命名约定进行了硬编码。未来的读者可能会找到更聪明的方法来做到这一点。要使用多个元素,比如 TwoCTAMixin,我只是扩展了基础 mixin 并添加 cta1_text,等等

CTAStructValue 需要访问该值,正如您对 @属性 变量所期望的那样。 .

def get_cta_href_value(cta, varname="cta"):
    """Function that returns the href link with a value provided.
       The value is returned in this order: (url > page > #)."""

    url_name = f"{varname}_url"
    page_name = f"{varname}_page"

    if cta[url_name] and cta[url_name] != "":
        return cta[url_name]
    elif cta[page_name] and cta[url_name] != "":
        return cta[page_name]
    return "#" # broken link, return something non-volatile


class CTAStructValue(blocks.StructValue):
    """Calculated properties for CTAMixin."""

    @property
    def cta_href(self):
        return get_cta_href_value(self)


class CTAMixin(blocks.StructBlock):
    """Mixin that includes a single CTA element."""

    cta_text = blocks.CharBlock(required=True, help_text="Text to display on the button")
    cta_url = blocks.URLBlock(required=False, help_text="URL the button directs to")
    cta_page = blocks.PageChooserBlock(required=False, help_text="Page the button directs to")

    class Meta:
        abstract = True


class SomeSectionBlock(CTAMixin):
    section_heading = blocks.CharBlock()

    class Meta:
        template = "blocks/some_section_block.html"

some_section_block.html

<section>
    <div class="wrapper some-section">
        <h2>{{ self.section_heading }}</h2>        

        <a href="{{ self.cta_href }}">
        <button>{{ self.cta_text }}</button>
        </a>
    </div>
</section>