Skip to content

Instantly share code, notes, and snippets.

@bartekbrak
Created February 20, 2013 11:06
Show Gist options
  • Save bartekbrak/4994828 to your computer and use it in GitHub Desktop.
Save bartekbrak/4994828 to your computer and use it in GitHub Desktop.
rebuild mptt tree
# -*- coding: UTF-8 -*-
from django.core.management.base import BaseCommand, CommandError
from cms.models.pagemodel import Page
from optparse import make_option
def rebuild_tree(parent, left=1, recursion_level=0, commit=False):
right = left + 1
page = Page.objects.filter(id=parent).get()
# element header
print "%s(%02d) %s" % ('\t' * recursion_level, page.id, page.get_title())
children = Page.objects.filter(parent=parent)
for child in children:
right = rebuild_tree(child.id, left=right, recursion_level=recursion_level + 1, commit=commit)
# element footer
print "%s%s-%s=>%s-%s " % ('\t' * recursion_level, page.lft, page.rght, left, right)
# save
page.lft = left
page.rght = right
if commit:
page.save()
return right + 1
class Command(BaseCommand):
args = '<page_id page_id ...> [--dry-run]'
help = """
This script attempts to rebuild a malformed django-cms-mptt tree. It checks the
parent_id field only. This means it will potentially reorder elements of the
same level as it does not check their left and right values. The output might
appear somewhat counter-intuitive to you, an element with children will have its
body split by children elements. Have a look at the example:
(id) parent_element_title
(id) child_element_title
13-14=>13-14 # child element footer
12-15=>12-15 # parent element footer
Numbers' format: left_before-right_before=>left_after-right_after.
You may either provide a list of ids that you want to rebuild (and children thereof)
or parse all top level elements by providing no command line arguments.
Adapted for python from http://www.sitepoint.com/hierarchical-data-database-3/
by tu-br, 1338913297 ;)
"""
option_list = BaseCommand.option_list + (
make_option('--dry-run',
action='store_true',
dest='dry-run',
default=False,
help='Don\'t commit, just list the tree with proposed changes. '),
)
def handle(self, *args, **options):
commit = False if options['dry-run'] else True # whether to commit changes
commit or self.stdout.write("### This is a dry run only. No changes will be made to the database. ###\n")
if len(args) > 0:
for page_id in args:
try:
page = Page.objects.get(pk=int(page_id))
rebuild_tree(page.id, commit=commit)
except Page.DoesNotExist:
raise CommandError('Page "%s" does not exist' % page_id)
else:
top_level_cms_pages = Page.objects.all().filter(parent=None)
for top_level_cms_page in top_level_cms_pages:
rebuild_tree(top_level_cms_page.id, commit=commit)
commit or self.stdout.write("### This is a dry run only. No changes will be made to the database. ###\n")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment