Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get parent page on creating new Wagtail Page

I need to change some field default value given a value from the parent page when creating a new page. When editing an existing page, this is not a problem, but when creating a new page, I need to set a default value for a field. I have tried overriding the admin form, on init for WagtailAdminPageForm, the parent_page parameter is empty. And if I try to do it on the init method form Page subclass, there is no arg or kwargs with the parent information.

is there a way to get the page for which the new page will be the parent?

This is what I tried on Page constructor

class CMSPage(Page):
    .
    .
    .
    def __init__(self, *args, **kwargs):
        super(BaseContentMixin, self).__init__(*args, **kwargs)

        if hasattr(self.get_parent().specific, 'published_site') and self.get_parent().specific.published_site == 'extranet':
            self.published_site = 'extranet'

This works editing a page, for new page, I get that NoneType objects has no attribute specific.

Django version is 1.10, Python version is 3.6, Wagtail version is 1.9

like image 936
Cheluis Avatar asked Jun 02 '17 13:06

Cheluis


1 Answers

After clarification of the question, here is a second answer that might be more suitable. Note that this requires Wagtail 1.11.x which as at this time is not yet released.

Example Code for Solution

First Create a new class for your custom page form, usually in models.py or wherever the model for your page is.

from wagtail.wagtailadmin.forms import WagtailAdminPageForm

class MyCustomPageForm(WagtailAdminPageForm):

    # Override the __init__ function to update 'initial' form values
    def __init__(self, data=None, files=None, parent_page=None, *args, **kwargs):
        print('parent_page', parent_page, parent_page.id, parent_page.title)
        # update the kwargs BEFORE the init of the super form class
        instance = kwargs.get('instance')
        if not instance.id:
            # only update the initial value when creating a new page
            kwargs.update(initial={
                # 'field': 'value'
                'title': parent_page.id  # can be anything from the parent page
            })
        # Ensure you call the super class __init__
        super(MyCustomPageForm, self).__init__(data, files, *args, **kwargs)
        self.parent_page = parent_page

Second On the page model definition, tell that model to use the form class you have defined

from wagtail.wagtailcore.models import Page

class MyCustomPage(Page):
    base_form_class = MyCustomPageForm

Explanation of Solution

  • Wagtail provides the ability to override the form class (note: not model class) that gets called when building the form for creation and editing in Wagtail Admin.
  • Documentation: Customising generated forms
  • Our custom form class will inherit the WagtailAdminPageForm class.
  • Inside this new form class, we want to define our own __init__ function, this is called when the form is created.
  • Note the Github code for the default definition of __init__ on WagtailAdminPageForm
  • To inject custom values, we will override the initial data in kwargs before the calling of the class' super __init__
  • We only want to do this when a new page is being created, so check that the instance has no id
  • We can access the parent_page instance and any fields in it
  • After adding our custom initial data, then we call the super __init__ with the changed kwargs
  • Note: The reason for the requirement of Wagtail 1.11.x is that previous versions until that point did not add parent_page when calling the class model until pull request 3508
like image 132
LB Ben Johnston Avatar answered Oct 23 '22 15:10

LB Ben Johnston