Wagtail unit testing: Adding child pages converts

2019-03-06 03:33发布

Trying to create some unit tests for Wagtail and running into the following problem:

>> 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" goes from being type ArticlePage to type Page in the page tree. Is this Page object a reference to the ArticlePage and there's a method I'm not aware of to fetch it, or am I missing something obvious here?

In the meantime I've worked around the problem by just storing the added article pages in a separate list, but I'd really like to understand what's going on here.

1条回答
\"骚年 ilove
2楼-- · 2019-03-06 04:17

Wagtail uses multi-table inheritance to represent pages: the fields that are common to all page types (such as title and slug, along with various internal ones used for things like tracking position within the page tree) are part of the base Page model that all page types inherit from. The additional fields you define on ArticlePage exist separately in their own table. When you retrieve a page instance, it can exist in one of two possible forms depending on which model you retrieve it through:

>> page = Page.objects.get(title='article1')
<Page: article1>

This is a basic Page instance, and only has access to properties like page.title, not fields/methods defined on ArticlePage.

>> page = ArticlePage.objects.get(title='article1')
<ArticlePage: article1>

This is a full ArticlePage instance, allowing you to refer to things like page.body.

Operations that traverse the page tree, such as get_tree() or get_children(), always give you basic Page instances. This is for performance reasons - there's no way to know in advance which page types you're going to get back, so it can't tell which tables to query in order to retrieve the full page data.

You can go from an individual Page instance into an instance of the more specific page model, by accessing the specific property - this will incur one extra database query:

>> page = Page.objects.get(title='article1')
>> page.specific
<ArticlePage: article1>

You can also call the specific() method on a PageQuerySet, which will perform one extra query for each distinct page type that exists in that queryset:

>> root.get_tree().specific()
<PageQuerySet [<FrontPage: article0>, <ArticlePage: article1>]>
查看更多
登录 后发表回答