将页面对象转换为其页面派生对象

Turning a Page Object Into Its Page Derived Object

我是鹡鸰的新手,但我一直运行做一些事情,我确信有比我目前正在做的更好的解决方案。

假设我有一个名为 ProductPage 的 Wagtail 页面。假设此页面有一个字段是另一个名为 related_product 的 ProductPage。当我尝试通过以下代码在我的模板或上下文中访问此页面时,

self.related_product

它 returns 一个 Page 对象而不是 ProductPage 对象。因此,如果不通过

将其转换为 ProductPage 对象,我将无法到达我真正想要的字段
ProductPage.objects.get(page_ptr_id=self.related_product.id)

必须有一种方法可以在没有上述查询的情况下对其进行转换。

Page 实例到更具体模型的标准方法是访问 specific 属性:

product_page = some_page.specific  # returns a ProductPage instance

但是,这将在内部执行数据库查询,因此它并不比上面的代码更有效(只是更具可读性)。如果你有一个 Pages 的查询集,你可以通过在查询集上调用 specific() 来稍微改进一下,这将对查询集中存在的每个不同页面类型执行一个额外的查询:

product_pages = product_index.get_children().specific()

不过,对于您的情况,有一个更好的解决方案:如果 related_product 字段仅用于 link 到 ProductPage 而不是任何其他类型的页面, 那么您应该通过将外键指向 ProductPage 而不是 Page:

来在数据模型中指出这一点
class ProductPage(Page):
    # ...
    related_product = models.ForeignKey('myapp.ProductPage', null=True, blank=True, on_delete=models.SET_NULL)

执行此操作时,访问 some_page.related_product 将始终为您提供 ProductPage 实例。作为一个额外的好处,Wagtail 管理中的页面选择器弹出窗口将确保您只能选择 ProductPages(如果您的所有 ProductPages 都在页面树中的同一位置,将直接带您到那里)。