Issue
I've defined a custom page model (a blog post) as a child of a parent model (a blog index page) and I want to test that the child can be created under its parent.
The BlogPage and BlogIndexPage models are copied from the wagtail "basic blog" example in the documentation, and works as expected.
I'm trying to follow the documentation but I get the following error:
AssertionError: Creating a page failed for an unknown reason
Through trial and error, I know that the error is caused by including an InlinePanel
that references another model (BlogPageGalleryImage
). If I remove this panel from my BlogPost model definition then the test will pass. I don't understand why including the panel causes an error, or how to solve this problem.
Any help is much appreciated!
The problematic line:
...
InlinePanel("gallery_images", label="Gallery images"),
...
The models:
class BlogIndexPage(Page):
template = "blog.html"
intro = models.TextField(blank=True)
subpage_types = ["cms.BlogPage", "cms.SimpleBlogPage", "cms.BlogTagIndexPage"]
def get_context(self, request):
# Update context to include only published posts, ordered by reverse-chron
context = super().get_context(request)
blogpages = self.get_children().live().order_by("-first_published_at")
context["blogpages"] = blogpages
return context
content_panels = Page.content_panels + [FieldPanel("intro", classname="full")]
class BlogPage(Page):
template = "blog-post.html"
parent_page_types = ["cms.BlogIndexPage"]
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = RichTextField(blank=True)
tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
categories = ParentalManyToManyField("cms.BlogCategory", blank=True)
def main_image(self):
gallery_item = self.gallery_images.first()
if gallery_item:
return gallery_item.image
else:
return None
search_fields = Page.search_fields + [
index.SearchField("intro"),
index.SearchField("body"),
]
content_panels = Page.content_panels + [
MultiFieldPanel(
[
FieldPanel("date"),
FieldPanel("tags"),
FieldPanel("categories", widget=forms.CheckboxSelectMultiple),
],
heading="Meta data",
),
FieldPanel("intro"),
FieldPanel("body"),
InlinePanel("gallery_images", label="Gallery images"),
]
class BlogPageGalleryImage(Orderable):
page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name="gallery_images")
image = models.ForeignKey("wagtailimages.Image", on_delete=models.CASCADE, related_name="+")
caption = models.CharField(blank=True, max_length=250)
panels = [
ImageChooserPanel("image"),
FieldPanel("caption"),
]
The test:
class MyPageTests(WagtailPageTests):
def setUp(self):
self.login()
indexPage = BlogIndexPage(title="Home page", path="blog", pk=1, depth=1)
indexPage.save()
page = BlogPage(
title="a blog post", intro="an intro", path="blog/post", depth=2, date="2022-02-23"
)
page.save()
image = Image(height=1, width=1)
image.save()
galleryImage = BlogPageGalleryImage(pk=1, page=page, image=image, caption="foo")
galleryImage.save()
category = BlogCategory(name="cat1", pk=1)
category.save()
def test_create_blog_post(self):
root_page = BlogIndexPage.objects.first()
data = {
"date": datetime.date(2022, 2, 28),
"title": "the title",
"intro": "the intro",
"depth": 2,
}
self.assertCanCreate(root_page, BlogPage, data)
Solution
The data passed to assertCanCreate
is a dict of HTTP form submission data to be handled by the 'create' view. When you have an InlinePanel as part of the creation form - even if you're not passing any data into it - there's a bundle of extra form fields that needs to be present, to tell it how many child forms are being submitted.
You can use the inline_formset
helper (in conjunction with the nested_form_data
helper which flattens the nested structure into a plain set of form fields) from Wagtail's testing utilities to construct a compatible form submission:
from wagtail.tests.utils.form_data import inline_formset, nested_form_data
class MyPageTests(WagtailPageTests):
# ...
def test_create_blog_post(self):
root_page = BlogIndexPage.objects.first()
data = nested_form_data({
"date": datetime.date(2022, 2, 28),
"title": "the title",
"intro": "the intro",
"gallery_images": inline_formset([])
})
self.assertCanCreate(root_page, BlogPage, data)
(You shouldn't need to include depth
in the form submission, as that's an internal database field used to keep track of the page's position in the page tree - and that's already taken care of in the assertCanCreate
call as you've specified root_page
as the parent page.)
Answered By - gasman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.