Тестирование Django Wagtail - утверждение, что под родительской страницей может быть создана дочерняя страница заданного типа с изображением
Я определил пользовательскую модель страницы (запись блога) как дочернюю модель родительской модели (индексная страница блога) и хочу проверить, что дочерняя модель может быть создана под родительской моделью.
Модели BlogPage и BlogIndexPage скопированы из примера wagtail "basic blog" в documentation, и работают как ожидалось.
Я пытаюсь следовать документации, но получаю следующую ошибку:
AssertionError: Creating a page failed for an unknown reason
Путем проб и ошибок я понял, что ошибка вызвана включением панели InlinePanel, которая ссылается на другую модель (BlogPageGalleryImage). Если я удалю эту панель из определения модели BlogPost, то тест пройдет. Я не понимаю, почему включение панели вызывает ошибку и как решить эту проблему.
Любая помощь будет очень признательна!
Проблемная строка:
...
InlinePanel("gallery_images", label="Gallery images"),
...
Модели:
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"),
]
Тест:
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)
Данные, передаваемые в assertCanCreate, являются диктом данных отправки HTTP-формы, которые должны быть обработаны представлением 'create'. Когда у вас есть InlinePanel как часть формы создания - даже если вы не передаете в нее никаких данных - есть пучок дополнительных полей формы, которые должны присутствовать , чтобы сообщить ей, сколько дочерних форм отправляется.
Вы можете использовать помощник inline_formset (в сочетании с помощником nested_form_data, который сглаживает вложенную структуру в простой набор полей формы) из утилит тестирования Wagtail для построения совместимой формы отправки:
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)
(Вам не нужно включать depth в отправку формы, так как это внутреннее поле базы данных, используемое для отслеживания позиции страницы в дереве страниц - и об этом уже позаботились в вызове assertCanCreate, так как вы указали root_page в качестве родительской страницы)