Example #1
0
 def get_root(self):
     """
     Get the root page for this menu
     """
     try:
         return Page.objects.get(title=self.menu_name, parent=None)
     except Page.DoesNotExist:
         raise Page.DoesNotExist("Menu does not exist.\nNo top-level page found with the title '%s'." % self.menu_name)
Example #2
0
def show_menu(context, menu_name, min_level, max_level, expand=None):

    menu_pages = []
    needed_pages = []

    try:
        root_page = Page.objects.get(title=menu_name, parent=None)
    except Page.DoesNotExist:
        raise Page.DoesNotExist(
            "Menu does not exist.\nNo top-level page found with the title '%s'."
            % menu_name)

    # Page.get_absolute_url() accesses self.parent recursively to build URLs
    # (assuming relative URLs).
    # This means that to render any menu item, we need all the ancestors up to
    # the root. Therefore it is more efficient to pull back this tree, without
    # min_level applied, and apply it just to decide which items to render.

    current_page = None
    if 'fiber_page' in context:
        current_page = context['fiber_page']

    if current_page and current_page.is_child_of(root_page):
        tree = root_page.get_descendants(include_self=True).filter(
            level__lte=max_level)
        if expand == 'all':
            needed_pages = tree
        else:
            if current_page.level + 1 < min_level:
                # Nothing to do
                needed_pages = []
            else:
                # We need the 'route' nodes, the 'sibling' nodes and the children
                route = tree.filter(lft__lt=current_page.lft,
                                    rght__gt=current_page.rght)

                # We show any siblings of anything in the route to the current page.
                # The logic here is that if the user drills down, menu items
                # shown previously should not disappear.

                # The following assumes that accessing .parent is cheap, which
                # it can be if current_page was loaded correctly.
                p = current_page
                sibling_qs = []
                while p.parent_id is not None:
                    sibling_qs.append(
                        tree.filter(level=p.level,
                                    lft__gt=p.parent.lft,
                                    rght__lt=p.parent.rght))
                    p = p.parent
                route_siblings = reduce(operator.or_, sibling_qs)

                children = tree.filter(lft__gt=current_page.lft,
                                       rght__lt=current_page.rght)
                if expand != 'all_descendants':
                    # only want immediate children:
                    children = children.filter(level=current_page.level + 1)

                needed_pages = route | route_siblings | children

    else:
        # Only show menus that start at the first level (min_level == 1)
        # when the current page is not in the menu tree.
        if min_level == 1:
            if not expand:
                needed_pages = Page.objects.filter(
                    tree_id=root_page.tree_id).filter(level__lte=1)
            elif expand == 'all':
                needed_pages = Page.objects.filter(
                    tree_id=root_page.tree_id).filter(level__lte=max_level)
            else:
                needed_pages = []

    needed_pages = Page.objects.link_parent_objects(needed_pages)

    # Now we need to do min_level filtering
    for p in needed_pages:
        if p.level >= min_level:
            menu_pages.append(p)

    # Remove pages that shouldn't be shown in the menu for the current user.
    user = context['user']
    menu_pages = [
        p for p in menu_pages
        if (p.is_public_for_user(user) and p.show_in_menu)
    ]
    """
    Order menu_pages for use with tree_info template tag.
    """
    menu_pages = sorted(menu_pages, key=lambda menu_page: menu_page.lft)
    """
    Find parent page for this menu
    """
    menu_parent_page = None
    if menu_pages:
        menu_parent_page = menu_pages[0].parent
    elif min_level == 1:
        menu_parent_page = root_page

    context['Page'] = Page
    context['fiber_menu_pages'] = menu_pages
    context['fiber_menu_parent_page'] = menu_parent_page
    context['fiber_menu_args'] = {
        'menu_name': menu_name,
        'min_level': min_level,
        'max_level': max_level,
        'expand': expand
    }
    return context
Example #3
0
def show_menu(context, menu_name, min_level, max_level, expand=None):

    menu_pages = []

    try:
        root_page = Page.objects.get(title=menu_name, parent=None)
    except Page.DoesNotExist:
        raise Page.DoesNotExist(
            "Menu does not exist.\nNo top-level page found with the title '%s'."
            % menu_name)

    current_page = None
    if 'fiber_page' in context and expand != 'all':
        current_page = context['fiber_page']

    if current_page and current_page.get_root() == root_page:
        """
        Get all siblings of the pages in the path from the root_node to the current page,
        plus the pages one level below the current page,
        but stay inside min_level and max_level
        """
        for page in current_page.get_ancestors():
            if min_level <= page.level:
                if page.level <= max_level:
                    menu_pages.extend(page.get_siblings(True))
                else:
                    break

        if min_level <= current_page.level <= max_level:
            menu_pages.extend(current_page.get_siblings(True))

        if min_level <= (current_page.level + 1) <= max_level:
            if not expand:
                menu_pages.extend(current_page.get_children())
            elif expand == 'all_descendants':
                menu_pages.extend(current_page.get_descendants())

    else:
        """
        Only show menus that start at the first level (min_level == 1)
        when the current page is not in the menu tree.
        """
        if min_level == 1:
            if not expand:
                menu_pages.extend(
                    Page.objects.filter(tree_id=root_page.tree_id).filter(
                        level=min_level))
            elif expand == 'all':
                menu_pages.extend(
                    Page.objects.filter(tree_id=root_page.tree_id).filter(
                        level__range=(min_level, max_level)))
    """
    Remove pages that the current user isn't supposed to see.
    """
    visible_pages_for_user = Page.objects.visible_pages_for_user(
        context['user']).filter(show_in_menu=True)
    menu_pages = list(set(menu_pages) & set(visible_pages_for_user))
    """
    Order menu_pages for use with tree_info template tag.
    """
    menu_pages = sorted(menu_pages, key=lambda menu_page: menu_page.lft)
    """
    Find parent page for this menu
    """
    menu_parent_page = None
    if menu_pages:
        menu_parent_page = menu_pages[0].parent
    elif min_level == 1:
        menu_parent_page = root_page

    context['Page'] = Page
    context['fiber_menu_pages'] = menu_pages
    context['fiber_menu_parent_page'] = menu_parent_page
    context['fiber_menu_args'] = {
        'menu_name': menu_name,
        'min_level': min_level,
        'max_level': max_level,
        'expand': expand
    }
    return context