Mev*_*abu 5 python django wagtail wagtail-streamfield
我想实现这样的目标,
from wagtail.wagtailcore.blocks import StreamBlock, StructBlock
class CarouselBlock(StructBlock):
content = StreamBlock([
('tab', TabBlock()),
('carousel', CarouselBlock())
])
class TabBlock(StructBlock):
content = StreamBlock([
('tab', TabBlock()),
('carousel', CarouselBlock())
])
Run Code Online (Sandbox Code Playgroud)
在轮播中,我可以添加一个选项卡或另一个轮播,在选项卡中我可以添加一个轮播或另一个选项卡。
处理此类编程案例的最佳实践是什么。
不幸的是,即使您找到了在定义中设置循环引用的方法,我也不认为有可能完成这项工作。Wagtail 的代码中有很多地方会尝试将定义作为树遍历,并以无限递归结束。
例如,在迁移中冻结 StreamField 定义时会发生这种情况 - 它会将任何对命名 StructBlock / StreamBlock 子类的引用扩展为普通的 StructBlock / StreamBlock 构造函数(请参阅http://docs.wagtail.io/en/v1.5.2/topics /streamfield.html#streamfield-definitions-within-migrations),在这种情况下会无限扩展。类似地,为编辑表单构建 HTML 将失败,因为它将尝试为表单中的每个可重复元素构建一个 HTML 模板(即每当您单击以添加新轮播或新选项卡时要添加的 HTML 块) - 而且对于顶级轮播、二级轮播、三级轮播等重复使用相同的模板是不够聪明的,因此将生成无限数量的模板。
您要么需要对嵌套级别的数量进行硬编码限制(例如 CarouselBlock 可以包含一个 SecondLevelCarousel 块,该块可以包含一个 ThirdLevelCarousel 块,但不能更多),或者想出一个替代数据表示将数据条目分布在多个视图中,而不是单个无限嵌套的表单中。例如,您可以将 Carousel 和 Tab 定义为片段模型,并使用 SnippetChooserBlock 定义它们之间的父/子链接:
@register_snippet
class Carousel(models.Model):
content = StreamField([
('carousel', blocks.SnippetChooserBlock('myapp.Carousel')),
('tab', blocks.SnippetChooserBlock('myapp.Tab')),
])
Run Code Online (Sandbox Code Playgroud)
(当然,如果你走这条路,你必须确保不要建立任何循环的父/子关系,否则你又回到了原点:-))