使用额外字段扩展Wagtail抽象模型的正确方法是什么?

时间:2017-01-16 01:10:19

标签: python django wagtail

我有一个带有几个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原则的严重违反。

1 个答案:

答案 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)