Example #1
0
    def handle(self, **options):
        any_problems_fixed = False

        for page in Page.objects.all():
            try:
                page.specific
            except page.specific_class.DoesNotExist:
                self.stdout.write(
                    "Page %d (%s) is missing a subclass record; deleting." %
                    (page.id, page.title))
                any_problems_fixed = True
                page.delete()

        (bad_alpha, bad_path, orphans, bad_depth,
         bad_numchild) = Page.find_problems()

        if bad_depth:
            self.stdout.write("Incorrect depth value found for pages: %s" %
                              self.numberlist_to_string(bad_depth))
        if bad_numchild:
            self.stdout.write("Incorrect numchild value found for pages: %s" %
                              self.numberlist_to_string(bad_numchild))

        if bad_depth or bad_numchild:
            Page.fix_tree(destructive=False)
            any_problems_fixed = True

        if orphans:
            # The 'orphans' list as returned by treebeard only includes pages that are
            # missing an immediate parent; descendants of orphans are not included.
            # Deleting only the *actual* orphans is a bit silly (since it'll just create
            # more orphans), so generate a queryset that contains descendants as well.
            orphan_paths = Page.objects.filter(id__in=orphans).values_list(
                'path', flat=True)
            filter_conditions = []
            for path in orphan_paths:
                filter_conditions.append(Q(path__startswith=path))

            # combine filter_conditions into a single ORed condition
            final_filter = functools.reduce(operator.or_, filter_conditions)

            # build a queryset of all pages to be removed; this must be a vanilla Django
            # queryset rather than a treebeard MP_NodeQuerySet, so that we bypass treebeard's
            # custom delete() logic that would trip up on the very same corruption that we're
            # trying to fix here.
            pages_to_delete = models.query.QuerySet(Page).filter(final_filter)

            self.stdout.write("Orphaned pages found:")
            for page in pages_to_delete:
                self.stdout.write("ID %d: %s" % (page.id, page.title))
            self.stdout.write('')

            if options.get('interactive', True):
                yes_or_no = input("Delete these pages? [y/N] ")
                delete_orphans = yes_or_no.lower().startswith('y')
                self.stdout.write('')
            else:
                # Running tests, check for the "delete_orphans" option
                delete_orphans = options.get('delete_orphans', False)

            if delete_orphans:
                deletion_count = len(pages_to_delete)
                pages_to_delete.delete()
                self.stdout.write(
                    "%d orphaned page%s deleted." %
                    (deletion_count, "s" if deletion_count != 1 else ""))
                any_problems_fixed = True

        if any_problems_fixed:
            # re-run find_problems to see if any new ones have surfaced
            (bad_alpha, bad_path, orphans, bad_depth,
             bad_numchild) = Page.find_problems()

        if any((bad_alpha, bad_path, orphans, bad_depth, bad_numchild)):
            self.stdout.write("Remaining problems (cannot fix automatically):")
            if bad_alpha:
                self.stdout.write(
                    "Invalid characters found in path for pages: %s" %
                    self.numberlist_to_string(bad_alpha))
            if bad_path:
                self.stdout.write("Invalid path length found for pages: %s" %
                                  self.numberlist_to_string(bad_path))
            if orphans:
                self.stdout.write("Orphaned pages found: %s" %
                                  self.numberlist_to_string(orphans))
            if bad_depth:
                self.stdout.write("Incorrect depth value found for pages: %s" %
                                  self.numberlist_to_string(bad_depth))
            if bad_numchild:
                self.stdout.write(
                    "Incorrect numchild value found for pages: %s" %
                    self.numberlist_to_string(bad_numchild))

        elif any_problems_fixed:
            self.stdout.write("All problems fixed.")
        else:
            self.stdout.write("No problems found.")
Example #2
0
    def handle(self, **options):
        any_problems_fixed = False

        for page in Page.objects.all():
            try:
                page.specific
            except page.specific_class.DoesNotExist:
                self.stdout.write("Page %d (%s) is missing a subclass record; deleting." % (page.id, page.title))
                any_problems_fixed = True
                page.delete()

        (bad_alpha, bad_path, orphans, bad_depth, bad_numchild) = Page.find_problems()

        if bad_depth:
            self.stdout.write("Incorrect depth value found for pages: %s" % self.numberlist_to_string(bad_depth))
        if bad_numchild:
            self.stdout.write("Incorrect numchild value found for pages: %s" % self.numberlist_to_string(bad_numchild))

        if bad_depth or bad_numchild:
            Page.fix_tree(destructive=False)
            any_problems_fixed = True

        if orphans:
            # The 'orphans' list as returned by treebeard only includes pages that are
            # missing an immediate parent; descendants of orphans are not included.
            # Deleting only the *actual* orphans is a bit silly (since it'll just create
            # more orphans), so generate a queryset that contains descendants as well.
            orphan_paths = Page.objects.filter(id__in=orphans).values_list('path', flat=True)
            filter_conditions = []
            for path in orphan_paths:
                filter_conditions.append(Q(path__startswith=path))

            # combine filter_conditions into a single ORed condition
            final_filter = functools.reduce(operator.or_, filter_conditions)

            # build a queryset of all pages to be removed; this must be a vanilla Django
            # queryset rather than a treebeard MP_NodeQuerySet, so that we bypass treebeard's
            # custom delete() logic that would trip up on the very same corruption that we're
            # trying to fix here.
            pages_to_delete = models.query.QuerySet(Page).filter(final_filter)

            self.stdout.write("Orphaned pages found:")
            for page in pages_to_delete:
                self.stdout.write("ID %d: %s" % (page.id, page.title))
            self.stdout.write('')

            if options.get('interactive', True):
                yes_or_no = input("Delete these pages? [y/N] ")
                delete_orphans = yes_or_no.lower().startswith('y')
                self.stdout.write('')
            else:
                # Running tests, check for the "delete_orphans" option
                delete_orphans = options.get('delete_orphans', False)

            if delete_orphans:
                deletion_count = len(pages_to_delete)
                pages_to_delete.delete()
                self.stdout.write(
                    "%d orphaned page%s deleted." % (deletion_count, "s" if deletion_count != 1 else "")
                )
                any_problems_fixed = True

        if any_problems_fixed:
            # re-run find_problems to see if any new ones have surfaced
            (bad_alpha, bad_path, orphans, bad_depth, bad_numchild) = Page.find_problems()

        if any((bad_alpha, bad_path, orphans, bad_depth, bad_numchild)):
            self.stdout.write("Remaining problems (cannot fix automatically):")
            if bad_alpha:
                self.stdout.write(
                    "Invalid characters found in path for pages: %s" % self.numberlist_to_string(bad_alpha)
                )
            if bad_path:
                self.stdout.write("Invalid path length found for pages: %s" % self.numberlist_to_string(bad_path))
            if orphans:
                self.stdout.write("Orphaned pages found: %s" % self.numberlist_to_string(orphans))
            if bad_depth:
                self.stdout.write("Incorrect depth value found for pages: %s" % self.numberlist_to_string(bad_depth))
            if bad_numchild:
                self.stdout.write(
                    "Incorrect numchild value found for pages: %s" % self.numberlist_to_string(bad_numchild)
                )

        elif any_problems_fixed:
            self.stdout.write("All problems fixed.")
        else:
            self.stdout.write("No problems found.")
    def handle(self, *args, **kwargs):
        # wagtail creates the root page for us
        root = Page.objects.get(slug='root')

        # NOTE: logic for creating pages based on wagtail core migration
        # 0002 initial data, which creates initial site and welcome page

        # delete default home wagtail home page
        Page.objects.filter(slug='home', title__contains='Welcome').delete()

        # Create PPA homepage
        home = HomePage.objects.filter(slug='home').first()
        if not home:
            home = HomePage.objects.create(
                title='Princeton Prosody Archive',
                slug='home',
                depth=2,
                numchild=0,
                show_in_menus=True,
                path='00010001',
                content_type=ContentType.objects.get_for_model(HomePage),
            )

        home.show_in_menus = True
        home.path = '00010001'
        home.url_path = '/home/'
        home.save()

        # create editorial index page
        editorial = EditorialIndexPage.objects.first()
        if not editorial:
            editorial = EditorialIndexPage.objects.create(
                title='Editorial',
                slug='editorial',
                depth=home.depth + 1,
                show_in_menus=False,
                path=home.path + '0001',
                content_type=ContentType.objects.get_for_model(EditorialIndexPage)
            )

        ## create collections page
        collections = CollectionPage.objects.first()
        if not collections:
            collections = CollectionPage.objects.create(
                title='About the Collections',
                slug='collections',
                depth=home.depth + 1,
                show_in_menus=False,
                path=home.path + '0002',
                content_type=ContentType.objects.get_for_model(CollectionPage)
            )

        # create content page stubs if they are not already present
        index = 3
        for slug, title in self.content_pages.items():
            cpage = Page.objects.filter(slug=slug).first()
            if not cpage:
                # use special contributor page for contributors
                if slug == 'contributors':
                    page_type = ContributorPage
                else:
                    page_type = ContentPage

                ContentPage.objects.create(
                    title=title,
                    slug=slug,
                    depth=home.depth + 1,
                    path='{}{:04d}'.format(home.path, index),
                    show_in_menus=True,
                    content_type=ContentType.objects.get_for_model(page_type)
                )
            index += 1

        # create wagtail site from django site and associate new homepage
        # self.create_wagtail_site(home)
        self.create_wagtail_site(home.page_ptr)

        # associate default page previews for home page if not set
        if not any([home.page_preview_1, home.page_preview_2]):
            home.page_preview_1 = ContentPage.objects.get(slug='prosody')
            home.page_preview_2 = ContentPage.objects.get(slug='history')
            home.save()

        # let treebeard fix the hierarchy
        Page.fix_tree()