尝试为Wagtail创建一些单元测试并遇到以下问题:
>> root = FrontPage.add_root(instance=FrontPageFactory.build())
>> root
<FrontPage: article0>
>> root.add_child(instance=ArticlePageFactory.build())
<ArticlePage: article1>
>> root.get_tree()
<PageQuerySet [<Page: article0>, <Page: article1>]>
“article0”从类型ArticlePage变为页面树中的类型Page。这个Page对象是对ArticlePage的引用吗?有一个我不知道要获取它的方法,还是我错过了一些明显的东西?
与此同时,我通过将添加的文章页面存储在单独的列表中解决了这个问题,但我真的很想了解这里发生了什么。
答案 0 :(得分:2)
Wagtail使用multi-table inheritance来表示页面:所有页面类型共有的字段(例如title和slug,以及用于跟踪页面树内位置等内容的各种内部字段)是所有页面类型都继承自的基本Page
模型。您在ArticlePage
上定义的其他字段分别存在于自己的表中。当您检索页面实例时,它可以以两种可能的形式之一存在,具体取决于您通过它检索的模型:
>> page = Page.objects.get(title='article1')
<Page: article1>
这是一个基本的Page
实例,只能访问page.title
等属性,而不能访问ArticlePage
上定义的字段/方法。
>> page = ArticlePage.objects.get(title='article1')
<ArticlePage: article1>
这是一个完整的ArticlePage
实例,允许您引用page.body
之类的内容。
遍历页面树的操作(例如get_tree()
或get_children()
)始终为您提供基本Page
个实例。这是出于性能原因 - 无法提前知道您要返回的页面类型,因此无法确定要查询的表格以便检索整页数据
您可以通过访问Page
属性,从单个specific
实例转到更具体的页面模型的实例 - 这将产生一个额外的数据库查询:
>> page = Page.objects.get(title='article1')
>> page.specific
<ArticlePage: article1>
您还可以在specific()
上调用PageQuerySet
方法,该方法将针对该查询集中存在的每种不同页面类型执行一次额外查询:
>> root.get_tree().specific()
<PageQuerySet [<FrontPage: article0>, <ArticlePage: article1>]>