Home > Mobile >  Testing Django Wagtail - assert that a child of the given Page type can be created under the parent,
Testing Django Wagtail - assert that a child of the given Page type can be created under the parent,

Time:03-05

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 validation error:

AssertionError: Validation errors found when creating a cms.blogpage:
E             date:
E               This field is required.
E             intro:
E               This field is required.
E             slug:
E               This field is required.
E             title:
E               This field is required.

I suspect that I'm defining my fixture incorrectly, but I am not what the correct form is. Any help is greatly appreciated! Can someone explain why it isn't working?

fixture (apps.cms.tests.fixtures.blogPage.json):

[
  {
    "model":"wagtailcore.page",
    "pk": 1,
    "fields":{
      "date":"2022-02-28",
      "intro":"intro to the post...",
      "slug":"slug/",
      "title":"the title",
      "body":"body of the post...",
      "categories":[
        1
      ],
      "content_type": ["cms", "blogpage"],
      "depth": 2
    }
  },
  {
    "model": "cms.blogpage",
    "pk": 1,
    "fields": {}
  }
]

the test class (apps.cms.tests.test_pages.py):

class MyPageTests(WagtailPageTests):
    def setUp(self):
        self.login()
        page = BlogIndexPage(title="Home page", slug="home", path="foo", depth=1)
        page.save()

    def test_create_blog_post(self):
        cwd = Path.cwd()
        root_page = BlogIndexPage.objects.first()
        with open(f"{cwd}/lettergun/apps/cms/tests/fixtures/BlogPage.json") as json_file:
            fixture = json.load(json_file)

        # Assert that a ContentPage can be made here, with this POST data
        self.assertCanCreate(root_page, BlogPage, nested_form_data(fixture))

the models (apps.cms.models.py):

class BlogIndexPage(Page):
    template = "blog.html"
    intro = models.TextField(blank=True)

    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 BlogPageTag(TaggedItemBase):
    content_object = ParentalKey("BlogPage", related_name="tagged_items", on_delete=models.CASCADE)


class BlogPage(Page):
    template = "blog-post.html"

    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="Blog information",
        ),
        FieldPanel("intro"),
        FieldPanel("body"),
        InlinePanel("gallery_images", label="Gallery images"),
    ]

CodePudding user response:

The last argument to self.assertCanCreate is a dictionary of HTTP POST data to be submitted to the 'create page' admin view. This is an entirely different thing to a fixture (which is a representation of the page data as stored in the database), and the data structures are not compatible.

At its simplest, the POST dictionary can just consist of the required fields date, intro, slug and title:

self.assertCanCreate(root_page, BlogPage, {
    'date': '2022-02-28',
    'intro': "intro to the post...",
    'slug': 'my-blog-page',
    'title': 'My blog page',
})

The nested_form_data helper is only needed if your test is creating a page with data that's more complex than a flat list of fields - for example, if you wanted your page data to contain some gallery images, you'd need to use it along with the inline_formset helper. As you have an InlinePanel on your page, you need to account for that even if you're not passing it any data - see https://stackoverflow.com/a/71356332/1853523 for details.

  • Related