我有一个带有几个StreamField
s 的抽象Wagtail模型.其中两个StreamField
位于管理视图中的单独选项卡中,这些选项卡将添加到edit_handler
.
class AbstractHomePage(Page): body = StreamField( HomePageStreamBlock(), default='' ) headingpanel = StreamField( HeadingPanelStreamBlock(), default='' ) sidepanel = StreamField( SidePanelStreamBlock(), default='' ) class Meta: abstract = True search_fields = Page.search_fields + [index.SearchField('body')] content_panels = Page.content_panels + [ StreamFieldPanel('body'), ] pagesection_panels = [ StreamFieldPanel('headingpanel'), StreamFieldPanel('sidepanel'), ] edit_handler = TabbedInterface([ ObjectList(content_panels), ObjectList(pagesection_panels, heading='Page sections'), ObjectList(Page.promote_panels), ObjectList(Page.settings_panels, classname='settings'), ])
我想扩展此模型并添加一个字段:
class Foo(AbstractHomePage): extra = models.TextField() Meta: verbose_name='Foo' content_panels = [ AbstractHomePage.content_panels[0], # title FieldPanel('extra'), AbstractHomePage.content_panels[-1] # streamfield ]
添加新的Foo页面时,管理面板中可用的唯一字段是来自的字段AbstractHomePage
.直到我更新新添加的字段不可用Foo
的edit_handler
:
class Foo(AbstractHomePage): extra = models.TextField() Meta: verbose_name='Foo' content_panels = [ AbstractHomePage.content_panels[0], # title FieldPanel('extra'), AbstractHomePage.content_panels[-1] # streamfield ] edit_handler = TabbedInterface([ ObjectList(content_panels), ObjectList(AbstractHomePage.pagesection_panels, heading='Page sections'), ObjectList(Page.promote_panels), ObjectList(Page.settings_panels, classname='settings'), ])
现在我的问题是:我做错了什么或没有遵循良好的编码习惯?
如果我必须更新edit_handler
每个扩展模型,有没有更好的方法来做到这一点?必须确保扩展模型的新添加字段每次AbstractHomePage
都会获得明确的"样板" edit_handler
块,感觉非常难看.我认为这是对DRY原则的严重违反.
你必须重新定义的原因edit_handler
中Foo
是Python的评估AbstractHomePage
类定义从上到下-在它遇到行点:
ObjectList(content_panels),
content_panels
被视为变量,而不是类属性,因此编辑处理程序是基于content_panels
该点存在的列表构建的.content_panels
在子类中重新定义不能覆盖它.
从本质上讲,您正在寻找一种方法来推迟构建edit_handler,直到定义了子类.我无法直接看到这样做的好方法,但我认为你可以通过重写方法来对Page.get_edit_handler
Wagtail内部进行一些挖掘来实现它:
from wagtail.utils.decorators import cached_classmethod class AbstractHomePage(Page): ... @cached_classmethod def get_edit_handler(cls): edit_handler = TabbedInterface([ ObjectList(cls.content_panels), ObjectList(cls.pagesection_panels, heading='Page sections'), ObjectList(cls.promote_panels), ObjectList(cls.settings_panels, classname='settings'), ]) return edit_handler.bind_to_model(cls)