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>
我需要创建一个可重复使用的元素(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>