Search code examples
djangowagtailrevisionaddchild

What is the proper way to create draft page programatically in the Wagtail?


Just to save page I do:

parent_page = Page.objects.get(title="parent")
page = Page(title="child", owner=request.user)
parent_page.add_child(instance=page)
page.save() # not sure if this required

What if I need to save Draft Page? This code seems to be working but I am not sure if it's correct:

parent_page = Page.objects.get(title="parent")
page = Page(title="child", live=False, owner=request.user)
parent_page.add_child(instance=page)
page.save_revision()
page.save()

Do I need call page.save() after page.save_revision()?

With this code everything works ok in my case but I have noticed that PageRevision.user_id is empty. How it can affect my code in future? From wagtail code I see that I can save revision with user parameter:

page.save_revision(user=request.user, log_action=True)

I have saved revisions without user and don't see any side effect. How this field is critical? Do I need to fill user_id field for all existing revisions?

P.S. looks like it would be better to wrap this code in transaction because when it fails due to validation error manage.py fixtree show me error Incorrect numchild value.


Solution

  • You don't need page.save() in either case - parent_page.add_child handles the saving. (This might be what's causing the manage.py fixtree issue - django-treebeard doesn't update in-memory instances after database operations, so fields like numchild may be getting saved with incorrect values.)

    The user field on revisions is optional, because changes to pages are not always performed by users - they might be done programmatically, like you are doing. It's just there for logging purposes (e.g. to show in the revision history of a page in the Wagtail admin).