我有一个带有几个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
的{{1}}:
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
块,感觉非常难看。我认为这是对DRY原则的严重违反。
答案 0 :(得分:6)
您必须在edit_handler
中重新定义Foo
的原因是Python会从上到下评估AbstractHomePage
类定义 - 在遇到该行时:
ObjectList(content_panels),
content_panels
被视为变量,而不是类属性,因此编辑处理程序是基于此时存在的content_panels
列表构建的。在子类中重新定义content_panels
不能覆盖它。
基本上,您正在寻找一种方法来推迟构建edit_handler,直到定义了子类。我无法直接看到这样做的好方法,但我认为你可以通过改写Wagtail内部来实现它,通过覆盖the Page.get_edit_handler
method:
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)