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

标签 python django wagtail

我有一个带有一些 StreamField 的抽象 Wagtail 模型。其中两个 StreamField 位于管理 View 的单独选项卡中,它们被添加到 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 中的字段。在我更新 Fooedit_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 block 感觉真的很难看。我认为这是对 DRY 原则的严重违反。

最佳答案

您必须在 Foo 中重新定义 edit_handler 的原因是 Python 从上到下评估 AbstractHomePage 类定义 - 在这一点上它遇到了这一行:

ObjectList(content_panels),

content_panels 被视为变量,而不是类属性,因此编辑处理程序是基于当时存在的 content_panels 列表构建的。在子类中重新定义 content_panels 不能覆盖它。

从本质上讲,您正在寻找一种方法来推迟构建 edit_handler 直到定义了子类。我看不到直接这样做的好方法,但我认为你可以通过覆盖 the Page.get_edit_handler method 来深入了解 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)

关于python - 使用额外字段扩展 Wagtail 抽象模型的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41668167/

相关文章:

python - pandas 中的过滤日期范围 raised `UserWarning: Boolean Series key will be reindexed to match DataFrame index.`

python - 异步 postgresql 查询的 subprocess 与 asyncio

django - 鹡鸰中的分页

html - 获取动态图像django/wagtail的图像源

Wagtail ModelAdmin 清理和验证相互依赖的字段

python - 如何修复 Python 游戏中的图像?

Python 使用 windows 命令行

python - Nginx 不为 Django 提供静态文件

python - Cloud 9中的Django-Haystack elasticsearch配置

python - 在Django中,我可以在创建对象时指定数据库吗?