使用 Wagtail CMS 使用 Python 检测 parent 和 child 页面类型

Detecting parent and child page types with Python using Wagtail CMS

我正在建立一个 Wagtail 网站。

将有一个事件索引页面,事件为 child 页。

每个活动页面也可以有 child 个页面,如果它是活动系列的一部分。

主要活动会将 child 活动显示为页面上的一系列链接。 child 事件还需要显示 parent 事件及其自己的同级事件。

在 models.py 我有一个事件 class。到目前为止,我正在检测 children,兄弟姐妹,parents 是这样的:

@property
def childpages(self):
    event_children = Event.objects.live().descendant_of(self)
    return event_children

@property
def parentpage(self):
    event_parent = self.get_parent()
    return event_parent

@property
def siblingpages(self):
    event_siblings = Event.objects.live().sibling_of(self, inclusive=False)
    return event_siblings

有没有办法找出 parent 页面类型是什么?如果它是事件索引,我不想在事件页面上显示它。我也不希望主要活动页面显示兄弟姐妹。

我用 not_child_of(somepage) 尝试过各种方法,但不太确定如何使用它。 'somepage' 指的是什么?一个class,一个变量?我习惯了 Javascript 并且对 Python 很陌生。

我会这样写:

@property
def parent_event(self):
    parent_page = self.get_parent()
    if parent_page.specific_class == Event:
        return parent_page.specific  # or just `return parent_page` if you don't need the extra detail from that page
    else:
        return None

@property
def sibling_events(self):
    parent_page = self.get_parent()
    if parent_page.specific_class == Event:
        return Event.objects.live().sibling_of(self, inclusive=False)
    else:
        # this is not a child event, so don't return siblings
        return Event.objects.none()

在 Python 中,检查对象是否是给定 class 实例的标准方法(即,在 Wagtail 术语中,页面是否属于特定类型)是 isinstance(parent_page, Event).

然而,对于 Wagtail 有一个额外的复杂性 - 当您使用 get_parentget_children 之类的方法在页面树中上下遍历时,它无法提前知道哪种页面类型它会返回 - 因此,出于性能原因,它将 return 类型为 Page 的 "minimal" 对象,其中仅包含所有页面共有的 title 属性.因此,self.get_parent().title 会起作用,但 self.get_parent().start_date 不会。要将其转换为正确类型的 "real" 对象,您需要访问 属性 specific,这将在后台执行额外的数据库请求以填充缺失的详细信息。

(请注意,当您 运行 明确要求特定类型页面的查询时,这不适用:对于 Event.objects.sibling_of(self) 这样的查询,我们知道我们会得到 Event 页,所以我们不需要对结果调用 specific。)

所以,if isinstance(parent_page, Event): 不会工作 - 它永远是错误的,因为那时 parent_page 是一个基本的 Page 对象(不管页面是否真的是EventEventIndex).

if isinstance(parent_page.specific, Event): 工作,但它有点低效,因为在 parent_page 是事件索引页面的情况下,你正在开火关闭您并不真正需要的额外数据库请求。更好的替代方法是使用 parent_page.specific_class,它会告诉您页面的具体类型,而无需触发额外的数据库请求。