Skip to content

Instantly share code, notes, and snippets.

@loicteixeira
Last active August 23, 2019 14:50
Show Gist options
  • Save loicteixeira/9e20d78d91b518bcbee9642874760c20 to your computer and use it in GitHub Desktop.
Save loicteixeira/9e20d78d91b518bcbee9642874760c20 to your computer and use it in GitHub Desktop.
[Wagtail] Create pages in migrations

Unfortunately because models returned by apps.get_model in migrations aren't the actual class, methods like Page.add aren't available and we have to do it manually. The most sensitive part being the handling of the path.

As an aside, deleting pages in migration will not update the numchild of the parent page. Unfortunately, the fixtree command doesn't play nice within a migration so it will need to be ran separately (or the parent page should manually be updated).

Notes: When not within a migration, a page path could be created with parent_page.get_last_child()._inc_path() or Page._get_children_path_interval(parent_page.path)[1].

from django.db import migrations
from treebeard.numconv import NumConv
# Values as of treebeard 4.2.0
PATH_ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
PATH_STEP_LENGTH = 4
PATH_NUM_CONV_BASE_FUNC = NumConv(len(PATH_ALPHABET), PATH_ALPHABET).int2str
def path_num_conv(num):
return PATH_NUM_CONV_BASE_FUNC(num).rjust(PATH_STEP_LENGTH, '0')
def add_child(apps, parent_page, klass, **kwargs):
"""
Replicate `Page.add_child` in migrations since it is not available in this context.
Originaly from http://www.agilosoftware.com/blog/django-treebard-and-wagtail-page-creation/
with a fix for the path.
"""
content_type_class = apps.get_model('contenttypes.ContentType')
page_content_type = content_type_class.objects.get(
model=klass.__name__.lower(),
app_label=klass._meta.app_label
)
url_path = '%s%s/' % (parent_page.url_path, kwargs.get('slug'))
path = parent_page.path + path_num_conv(parent_page.numchild + 1)
created_page = klass.objects.create(
content_type=page_content_type,
path=path,
depth=parent_page.depth + 1,
numchild=0,
url_path=url_path,
**kwargs
)
parent_page.numchild += 1
parent_page.save()
return created_page
def forwards(apps, schema_editor):
homepage_class = apps.get_model('core.HomePage')
homepage = homepage_class.objects.get()
mypage_class = apps.get_model('core.MyPage')
mypage = add_child(apps, homepage, mypage_class, title='FooBarBaz', slug='foobarbaz')
class Migration(migrations.Migration):
dependencies = [
...
]
operations = [
migrations.RunPython(forwards, migrations.RunPython.noop),
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment