class MainMenu(InclusionTag):
    name = 'main_menu'
    template = 'menu/dummy.html'

    options = Options(
        StringArgument(
            'template',
            default='bootstrap{}/menu/navbar.html'.format(BOOTSTRAP),
            required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        IntegerArgument('offset', default=0, required=False),
        IntegerArgument('limit', default=100, required=False),
        Flag('embody_root', default=False, true_values=['embody_root']),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, template, namespace, root_id, offset, limit,
                    embody_root, next_page):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        start_level = 0

        if next_page:
            children = next_page.children
        else:
            menu_renderer = context.get('cms_menu_renderer')

            if not menu_renderer:
                menu_renderer = menu_pool.get_renderer(request)

            nodes = menu_renderer.get_nodes(namespace, root_id)
            if root_id:
                # find the root id and cut the nodes
                id_nodes = menu_pool.get_nodes_by_attribute(
                    nodes, "reverse_id", root_id)
                if id_nodes:
                    node = id_nodes[0]
                    nodes = node.children
                    for remove_parent in nodes:
                        remove_parent.parent = None
                    start_level = node.level + 1
                    nodes = flatten(nodes)
                    if embody_root:
                        node.level = start_level
                        nodes.insert(0, node)
                else:
                    nodes = []
            children = cut_levels(nodes, start_level)
            children = menu_renderer.apply_modifiers(children,
                                                     namespace,
                                                     root_id,
                                                     post_cut=True)
            children = children[offset:offset + limit]
        context.update({'children': children, 'template': template})
        return context
class MainMenuBelowId(MainMenu):
    name = 'main_menu_below_id'
    options = Options(
        Argument('root_id', default=None, required=False),
        StringArgument('template',
                       default='cascade/bootstrap3/navbar-menu.html',
                       required=False),
        StringArgument('namespace', default=None, required=False),
    )
Example #3
0
class MainMenuBelowId(MainMenu):
    name = 'main_menu_below_id'
    options = Options(
        Argument('root_id', default=None, required=False),
        StringArgument('template', default='bootstrap/menu/navbar.html', required=False),
        IntegerArgument('offset', default=0, required=False),
        IntegerArgument('limit', default=100, required=False),
        StringArgument('namespace', default=None, required=False),
        Flag('embody_root', default=False, true_values=['embody_root']),
    )
Example #4
0
class MainMenuEmbodyId(MainMenu):
    name = 'main_menu_embody_id'
    options = Options(
        Argument('root_id', default=None, required=False),
        StringArgument('template',
                       default='bootstrap/menu/navbar.html',
                       required=False),
        StringArgument('namespace', default=None, required=False),
        Flag('embody_root', default=True, false_values=['skip_root']),
    )
Example #5
0
class MainMenuEmbodyId(MainMenu):
    name = 'main_menu_embody_id'
    options = Options(
        Argument('root_id', default=None, required=False),
        StringArgument('template', default='bootstrap{}/menu/navbar.html'.format(BOOTSTRAP), required=False),
        IntegerArgument('offset', default=0, required=False),
        IntegerArgument('limit', default=100, required=False),
        StringArgument('namespace', default=None, required=False),
        Flag('embody_root', default=True, false_values=['skip_root']),
        Argument('next_page', default=None, required=False),
    )
class MainMenu(ShowMenu):
    name = 'main_menu'

    options = Options(
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        StringArgument('template', default='cms/bootstrap3/main-menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, from_level, to_level, template, namespace, root_id, next_page):
        return super(MainMenu, self).get_context(context, from_level, to_level, 100, 100, template, namespace, root_id, next_page)
Example #7
0
class Paginator(InclusionTag):
    name = 'paginator'
    template = 'bootstrap/components/paginator.html'

    options = Options(
        IntegerArgument('page_range', default=5, required=False),
        StringArgument('template', default=None, required=False),
    )

    def get_context(self, context, page_range, template):
        try:
            current_page = int(context['request'].GET['page'])
        except (KeyError, ValueError):
            current_page = 1
        page_range -= 1
        template = template or self.template
        context.update({'template': template})
        paginator = context.get('paginator') or getattr(context.get('request'), 'paginator', None)
        if paginator:
            first_page = max(1, min(current_page - page_range / 2, paginator.num_pages - page_range))
            last_page = min(first_page + page_range, paginator.num_pages)
            context.update({
                'show_paginator': paginator.num_pages > 1,
                'show_aquos': paginator.num_pages > page_range + 1,
                'pages': [{'num': p, 'active': p == current_page} for p in range(first_page, last_page + 1)],
                'laquo': {'num': first_page - 1, 'paginate': first_page > 1},
                'raquo': {'num': last_page + 1, 'paginate': last_page < paginator.num_pages},
            })
        return context
Example #8
0
class MenuIcon(InclusionTag):
    name = 'menu_icon'
    template = 'bootstrap{}/components/menu-icon.html'.format(BOOTSTRAP)

    options = Options(
        Argument('child_id'),
        StringArgument('template', default=None, required=False),
    )

    def get_template(self, context, template=None, **kwargs):
        return template if template else self.template

    def get_context(self, context, child_id, template):
        try:
            cascadepage = Page.objects.get(id=child_id).cascadepage
        except (Page.DoesNotExist, AttributeError):
            pass
        else:
            icon_font, symbol = cascadepage.icon_font, cascadepage.menu_symbol
            if icon_font and symbol:
                prefix = icon_font.config_data.get('css_prefix_text', 'icon-')
                font_attr = 'class="{}{}"'.format(prefix, symbol)
                context.update({
                    'stylesheet_url': icon_font.get_stylesheet_url(),
                    'icon_font_attrs': mark_safe(font_attr),
                })
        return context

    def render_tag(self, context, **kwargs):
        context.push()
        output = super(MenuIcon, self).render_tag(context, **kwargs)
        context.pop()
        return output
Example #9
0
class MainMenu(InclusionTag):
    name = 'main_menu'
    template = 'menu/dummy.html'

    options = Options(
        StringArgument('template',
                       default='bootstrap/menu/navbar.html',
                       required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Flag('embody_root', default=False, true_values=['embody_root']),
    )

    def get_context(self, context, template, namespace, root_id, embody_root):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        start_level = 0
        nodes = menu_pool.get_nodes(request, namespace, root_id)
        if root_id:
            # find the root id and cut the nodes
            id_nodes = menu_pool.get_nodes_by_attribute(
                nodes, "reverse_id", root_id)
            if id_nodes:
                node = id_nodes[0]
                nodes = node.children
                for remove_parent in nodes:
                    remove_parent.parent = None
                start_level = node.level + 1
                nodes = flatten(nodes)
                if embody_root:
                    node.level = start_level
                    nodes.insert(0, node)
            else:
                nodes = []
        children = cut_levels(nodes, start_level)
        children = menu_pool.apply_modifiers(children,
                                             request,
                                             namespace,
                                             root_id,
                                             post_cut=True)
        context.update({'children': children, 'template': template})
        return context
class ShowTagsFilter(InclusionTag):
    name = 'show_tags_filter'
    template = 'workmate/filters/tags_filter.html'

    options = Options(
        StringArgument('related_model', default=None, required=True),
        StringArgument('url', default=None, required=True),
    )

    def get_context(self, context, related_model, url):
        request = context['request']
        tag_id = request.GET.get('tag')
        tags = Tag.onsite.all().annotate(count=Count(related_model))
        context['tags'] = tags
        context['url'] = url
        context['selected_tag'] = tags.filter(
            id__iexact=int(tag_id))[0] if tag_id else None
        return context
Example #11
0
class ShowSurvey(InclusionTag):
    """
    render a survey
    - slug: slug of the survey to render
    - lang: language used to render the survey
    - template: template used to render the survey
    """
    name = 'show_survey'
    template = 'multilingual_survey/survey.html'

    options = Options(
        StringArgument('slug', required=True),
        StringArgument('lang', default=settings.LANGUAGE_CODE, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
    )

    def get_context(self, context, slug, lang, template):
        try:
            # If there's an exception (500),
            # default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'multilingual_survey/empty.html'}

        # FIXME
        # Get survey data
        try:
            survey = Survey.objects.get(slug=slug)
            form = ResponseForm(request=request, survey=survey)

        except Survey.DoesNotExist:
            return {'error': 'Survey does not exist'}

        try:
            context.update({
                'response_form': form,
                'survey': survey,
                'template': template,
            })
        except:
            context = {"template": template}
        return context
Example #12
0
class ShowMenu(InclusionTag):
    name = 'show_menu'
    template = 'workmate/menu/dummy.html'

    options = Options(
        StringArgument('template', default='workmate/menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, template, namespace, next_page):
        request = context['request']
        nodes = menu_pool.get_nodes(request, namespace)
        nodes = check_visibility(nodes)
        nodes = sorted(nodes, key=lambda n: (n.menu_sort_order, n.menu_title, n.sort_order, n.title))

        context['nodes'] = nodes
        context['template'] = template
        context['namespace'] = namespace

        return context
class ShowPagesAroundPage(InclusionTag):
    """
    give the one level deep neighbour of a page
    """
    name = 'dju_show_pages_around_page'
    template = 'dju_page_thumbnail/dju_show_pages_around_page.html'

    options = Options(
        StringArgument(
            'template',
            default='dju_page_thumbnail/dju_show_pages_around_page.html',
            required=False), )

    def get_context(self, context, template):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        currentPage = request.current_page

        def get_info(page):
            try:
                imageurl = page.djupagethumbnail.image.url
            except:
                imageurl = ''
            return page.get_absolute_url(), page.get_title(), imageurl

        scanval = [('parent', [currentPage.get_parent()]),
                   ('siblings', currentPage.get_siblings()),
                   ('descendants', currentPage.get_descendants())]
        data = {}
        for datatype, objectslist in scanval:
            datalist = []
            for p in objectslist:
                abs_url, title, imageurl = get_info(p)
                datalist.append({
                    'abs_url': abs_url,
                    'title': title,
                    'imageurl': imageurl
                })
            data[datatype] = datalist
        try:
            context.update({'data': data, 'template': template})
        except:
            context = {'template': template}
        return context
Example #14
0
class Subscribe(InclusionTag):
    name = 'mailchimp_subscribe_form'
    template = 'cmsplugin_mailchimp/subscribe.html'
    options = Options(
        Argument('list_id'),
        StringArgument('template',
                       default='cmsplugin_mailchimp/subscribe.html',
                       required=False),
    )

    def get_context(self, context, list_id, template):
        subscribeForm = SubscribeForm(initial={'list_id': list_id})
        return context.update({
            'csrf_token': context['csrf_token'],
            'form': subscribeForm,
            'template': template,
        })
class ShowMenu(InclusionTag):
    """
    render a nested list of all children of the pages
    - from_level: starting level
    - to_level: max level
    - extra_inactive: how many levels should be rendered of the not active tree?
    - extra_active: how deep should the children of the active node be rendered?
    - namespace: the namespace of the menu. if empty will use all namespaces
    - root_id: the id of the root node
    - template: template used to render the menu
    """
    name = 'dju_show_menu'
    template = 'dju_page_thumbnail/F_DEBUG_menu_arround.html'

    options = Options(
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, from_level, to_level, extra_inactive,
                    extra_active, template, namespace, root_id, next_page):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        activeul = ''
        activehref = ''

        menu_renderer = context.get('cms_menu_renderer')
        if not menu_renderer:
            menu_renderer = menu_pool.get_renderer(request)

        if next_page:
            children = next_page.children
        else:
            # new menu... get all the data so we can save a lot of queries
            nodes = menu_renderer.get_nodes(request, namespace, root_id)
            if root_id:  # find the root id and cut the nodes
                id_nodes = menu_renderer.get_nodes_by_attribute(
                    nodes, "reverse_id", root_id)
                if id_nodes:
                    node = id_nodes[0]
                    nodes = node.children
                    for remove_parent in nodes:
                        remove_parent.parent = None
                    from_level += node.level + 1
                    to_level += node.level + 1
                    nodes = flatten(nodes)
                else:
                    nodes = []

        nodes = menu_renderer.get_nodes(request, namespace, root_id)

        isleafnode = False
        for n in nodes:
            if n.selected:
                if n.is_leaf_node:
                    isleafnode = True
                    ancestor = "/".join(
                        n.get_absolute_url().split('/')[0:-3]) + '/'
                    directancestor = "/".join(
                        n.get_absolute_url().split('/')[0:-2]) + '/'
                    from_level = n.level - 2
                else:
                    ancestor = "/".join(
                        n.get_absolute_url().split('/')[0:-2]) + '/'
                    directancestor = "/".join(
                        n.get_absolute_url().split('/')[0:-1]) + '/'
                    from_level = n.level - 1
                activehref = n
                #           print "ancestor",n.get_absolute_url(),ancestor,directancestor,from_level
                continue

        for n in nodes:
            #        print n.get_absolute_url() ==  directancestor,n.get_absolute_url(),directancestor
            if n.get_absolute_url() == directancestor:
                activeul = n
                continue

        to_level = from_level + 2
        if next_page:
            to_level = 100
            children = next_page.children
        else:

            children = cut_levels(nodes, from_level, to_level, extra_inactive,
                                  extra_active)
            children = menu_pool.apply_modifiers(children,
                                                 request,
                                                 namespace,
                                                 root_id,
                                                 post_cut=True)

        #print "activeul",activeul.get_absolute_url()
        #print "activehref",activehref.get_absolute_url()
        #print "ancestor",ancestor
        #print "directancestor",directancestor
        #print "BEFORE children",children

        newChildren = []
        for i in children:
            #print i.level,i.get_absolute_url(),
            if i.get_absolute_url().startswith(ancestor[:-1]):
                #print "kept",
                newChildren.append(i)
            #print ""

        try:
            #print "AFTER children",newChildren
            context.update({
                'children': newChildren,
                'activehref': activehref,
                'activeul': activeul,
                'ancestor': ancestor,
                'template': template,
                'from_level': from_level,
                'to_level': to_level,
                'extra_inactive': extra_inactive,
                'extra_active': extra_active,
                'namespace': namespace
            })
        except:
            context = {"template": template}
        return context
Example #16
0
class ShowMultipleMenu(ShowMenu):
    name = 'show_named_menu'

    options = Options(
        StringArgument('menu_name', required=True),
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, **kwargs):

        menu_name = kwargs.pop('menu_name')

        context.update({
            'children': [],
            'template': kwargs.get('template'),
            'from_level': kwargs.get('from_level'),
            'to_level': kwargs.get('to_level'),
            'extra_inactive': kwargs.get('extra_inactive'),
            'extra_active': kwargs.get('extra_active'),
            'namespace': kwargs.get('namespace')
        })

        try:
            named_menu = CMSNamedMenu.objects.get(name__iexact=menu_name).pages
        except ObjectDoesNotExist:
            logging.warn("Named CMS Menu %s not found" % menu_name)
            return context

        nodes = menu_pool.get_nodes(context['request'], kwargs['namespace'],
                                    kwargs['root_id'])

        context.update({
            'children':
            self.arrange_nodes(nodes,
                               named_menu,
                               namespace=kwargs['namespace'])
        })

        return context

    def arrange_nodes(self, node_list, node_config, namespace=None):

        arranged_nodes = []

        for item in node_config:
            item.update({'namespace': namespace})
            node = self.create_node(item, node_list)
            if node is not None:
                arranged_nodes.append(node)

        return arranged_nodes

    def create_node(self, item, node_list):

        item_node = self.get_node_by_id(item['id'],
                                        node_list,
                                        namespace=item['namespace'])
        if item_node is None:
            return None

        for child_item in item.get('children', []):

            child_node = self.get_node_by_id(child_item['id'],
                                             node_list,
                                             namespace=item['namespace'])
            if child_node is not None:
                item_node.children.append(child_node)

        return item_node

    def get_node_by_id(self, id, nodes, namespace=None):

        final_node = None

        try:
            for node in nodes:

                if node.id == id:
                    if namespace:
                        if node.namespace == namespace:
                            final_node = node
                            break
                    else:
                        final_node = node
                        break

            if final_node is None:
                """ If we're editing a page, we need to find
                    the draft version of the page and turn it
                    into a navigation node """

                page = get_page_draft(Page.objects.get(id=id))

                final_node = page_to_node(page, page, 0)

            final_node.children = []
            final_node.parent = []
        except:
            logger.exception('Failed to find node')

        return final_node
class ShowNamedMenu(ShowMenu):

    name = 'show_named_menu'

    options = Options(
        StringArgument('menu_name_or_slug', required=True),
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, menu_name_or_slug, from_level, to_level,
                    extra_inactive, extra_active, template, namespace, root_id,
                    next_page):

        # From menus.template_tags.menu_tags.py
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        if next_page:
            children = next_page.children
        else:

            # new menu... get all the data so we can save a lot of queries
            menu_renderer = context.get('cms_menu_renderer')

            if not menu_renderer:
                menu_renderer = menu_pool.get_renderer(request)

            # Get Nodes hopefully from cached page nodes above in context
            nodes = menu_renderer.get_nodes(namespace, root_id)
            nodes = filter_nodes(nodes)

            # Ceate a page_node dictionary
            page_nodes = {n.id: n for n in nodes}

            # Get if in Draft or Published mode
            draft_mode_active = use_draft(request)

            # Get Language to ensure separate cache of page nodes
            language = getattr(request, 'LANGUAGE_CODE', "")

            # Build or get from cache - Named menu nodes
            nodes = build_named_menu_nodes(menu_name_or_slug,
                                           page_nodes,
                                           draft_mode_active,
                                           language,
                                           namespace=namespace)

            # If nodes returned, then cut levels and apply modifiers
            if nodes:
                # Post-Cut ... apply cut levels and menu modifiers
                nodes = flatten(nodes)
                children = cut_levels(nodes, from_level, to_level,
                                      extra_inactive, extra_active)
                children = menu_renderer.apply_modifiers(children,
                                                         namespace,
                                                         root_id,
                                                         post_cut=True)
            else:
                children = []

        # Return the context, or go straight to template which will present missing etc.
        try:
            context['children'] = children
            context['template'] = template
            context['from_level'] = from_level
            context['to_level'] = to_level
            context['extra_inactive'] = extra_inactive
            context['extra_active'] = extra_active
            context['namespace'] = namespace
        except:
            context = {"template": template}

        return context
Example #18
0
class ShowMenu(InclusionTag):
    """
    render a nested list of all children of the pages
    - from_level: starting level
    - to_level: max level
    - extra_inactive: how many levels should be rendered of the not active tree?
    - extra_active: how deep should the children of the active node be rendered?
    - namespace: the namespace of the menu. if empty will use all namespaces
    - root_id: the id of the root node
    - template: template used to render the menu
    """
    name = 'show_menu'
    template = 'menu/dummy.html'

    options = Options(
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, from_level, to_level, extra_inactive,
                    extra_active, template, namespace, root_id, next_page):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        if next_page:
            children = next_page.children
        else:
            # new menu... get all the data so we can save a lot of queries
            menu_renderer = context.get('cms_menu_renderer')

            if not menu_renderer:
                menu_renderer = menu_pool.get_renderer(request)

            nodes = menu_renderer.get_nodes(namespace, root_id)
            if root_id:  # find the root id and cut the nodes
                id_nodes = menu_pool.get_nodes_by_attribute(
                    nodes, "reverse_id", root_id)
                if id_nodes:
                    node = id_nodes[0]
                    nodes = node.children
                    for remove_parent in nodes:
                        remove_parent.parent = None
                    from_level += node.level + 1
                    to_level += node.level + 1
                    nodes = flatten(nodes)
                else:
                    nodes = []
            children = cut_levels(nodes, from_level, to_level, extra_inactive,
                                  extra_active)
            children = menu_renderer.apply_modifiers(children,
                                                     namespace,
                                                     root_id,
                                                     post_cut=True)

        try:
            context['children'] = children
            context['template'] = template
            context['from_level'] = from_level
            context['to_level'] = to_level
            context['extra_inactive'] = extra_inactive
            context['extra_active'] = extra_active
            context['namespace'] = namespace
        except:
            context = {"template": template}
        return context
class ShowMultipleMenu(ShowMenu):
    name = 'show_named_menu'

    options = Options(
        StringArgument('menu_name', required=True),
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, **kwargs):

        # Get the name and derive the slug - for the cache key
        menu_name = kwargs.pop('menu_name')
        menu_slug = slugify(menu_name)

        context.update({
            'children': [],
            'template': kwargs.get('template'),
            'from_level': kwargs.get('from_level'),
            'to_level': kwargs.get('to_level'),
            'extra_inactive': kwargs.get('extra_inactive'),
            'extra_active': kwargs.get('extra_active'),
            'namespace': kwargs.get('namespace')
        })

        lang = get_language()

        request = context['request']
        namespace = kwargs['namespace']
        root_id = kwargs['root_id']

        # Try to get from Cache first
        arranged_nodes = cache.get(menu_slug, lang)

        # Create menu from Json if not
        if arranged_nodes is None:
            logger.debug(u'Creating menu "%s %s"', menu_slug, lang)
            named_menu = None
            arranged_nodes = []

            # Get by Slug or from Menu name - backwards compatible
            try:
                named_menu = CMSNamedMenu.objects.get(
                    slug__exact=menu_slug).pages
            except ObjectDoesNotExist:
                try:
                    named_menu = CMSNamedMenu.objects.get(
                        name__iexact=menu_name).pages
                except ObjectDoesNotExist:
                    logger.info(
                        u'Named menu with name(slug): "%s (%s)" not found',
                        menu_name, lang)

            # If we get the named menu, build the nodes
            if named_menu:
                # Try to get all the navigation nodes from the cache, or repopulate if not
                nodes = getattr(request, NODES_REQUEST_CACHE_ATTR, None)
                if nodes is None:
                    nodes = get_nodes(request, namespace, root_id)
                    # getting nodes is slow, cache on request object will
                    # speedup if more than one named menus are on the page
                    setattr(request, NODES_REQUEST_CACHE_ATTR, nodes)

                # Get the named menu nodes
                arranged_nodes = self.arrange_nodes(nodes,
                                                    named_menu,
                                                    namespace=namespace)
                if len(arranged_nodes) > 0:
                    logger.debug(u'Put %i menu "%s %s" to cache',
                                 len(arranged_nodes), menu_slug, lang)
                    cache.set(menu_slug, lang, arranged_nodes)
                else:
                    logger.debug(u'Don\'t cache empty "%s %s" menu!',
                                 menu_slug, lang)
        else:
            logger.debug(u'Fetched menu "%s %s" from cache', menu_slug, lang)

        context.update({'children': arranged_nodes})

        return context

    def arrange_nodes(self, node_list, node_config, namespace=None):
        arranged_nodes = []
        for item in node_config:
            node = self.create_node(item, node_list, namespace)
            if node is not None:
                arranged_nodes.append(node)
        return arranged_nodes

    def create_node(self, item, node_list, namespace=None):
        # Get Item node
        item_node = self.get_node_by_id(item['id'], node_list, namespace)
        if item_node is None:
            return None

        if item_node.attr.get('cms_named_menus_generate_children', False):
            # Dynamic children
            # NOTE: We have to collect the children manually because get_node_by_id cleans the hierarchy
            child_items = [{
                'id': node.id
            } for node in node_list if node.parent_id == item['id']]
            if len(child_items) == 0:
                logger.warn(u'Empty children for %s', item_node.title)
        else:
            # Child menu items defined in the menu
            child_items = item.get('children', [])

        # If child items, call recursively
        if child_items:
            for child_item in child_items:
                child_node = self.create_node(child_item, node_list, namespace)
                if child_node:
                    item_node.children.append(child_node)

        return item_node

    def get_node_by_id(self, id, nodes, namespace):  # @ReservedAssignment
        from copy import deepcopy
        final_node = None
        try:
            for node in nodes:
                if node.id == id and (not namespace
                                      or node.namespace == namespace):
                    final_node = node
                    break
        except:
            logger.exception('Failed to find node')
        if final_node is not None:
            final_node.parent = None
            final_node.children = []
            # Return Deepcopy which allows duplicated nodes throughout
            return deepcopy(final_node)

        return None
class ShowMenuArround(InclusionTag):
    """
    render a nested list of all children of the pages
    - from_level: starting level
    - to_level: max level
    - extra_inactive: how many levels should be rendered of the not active tree?
    - extra_active: how deep should the children of the active node be rendered?
    - namespace: the namespace of the menu. if empty will use all namespaces
    - root_id: the id of the root node
    - template: template used to render the menu
    """
    name = 'dju_show_menu_arround'
    template = 'dju_page_thumbnail/F_DEBUG_menu_arround.html'

    options = Options(
        IntegerArgument('from_level', default=0, required=False),
        IntegerArgument('to_level', default=100, required=False),
        IntegerArgument('extra_inactive', default=0, required=False),
        IntegerArgument('extra_active', default=1000, required=False),
        StringArgument('template', default='menu/menu.html', required=False),
        StringArgument('namespace', default=None, required=False),
        StringArgument('root_id', default=None, required=False),
        Argument('next_page', default=None, required=False),
    )

    def get_context(self, context, from_level, to_level, extra_inactive,
                    extra_active, template, namespace, root_id, next_page):
        try:
            # If there's an exception (500), default context_processors may not be called.
            request = context['request']
        except KeyError:
            return {'template': 'menu/empty.html'}

        menu_renderer = context.get('cms_menu_renderer')
        if not menu_renderer:
            menu_renderer = menu_pool.get_renderer(request)
        if next_page:
            # getting the nodel level
            nodes = menu_renderer.get_nodes(request, namespace, root_id)
            for n in nodes:
                if n.selected:
                    level = n.level

            # getting the children
            children = []
            for n in next_page.children:

                # in fact these are mutually exclusive  either we are a descendant either a sibling
                if n.descendant and n.level < level + 2:
                    children.append(n)

                if n.sibling or n.selected:
                    children.append(n)

        else:
            nodes = menu_renderer.get_nodes(request, namespace, root_id)
            # we find the closest ancestor (that is the one with the highest level but in fact
            # it looks like the nodes are scanned from the top to bottom that is the lowest to the highest.
            for n in nodes:
                if n.ancestor:
                    children = [n]

        try:
            context.update({
                'children': children,
                'template': template,
                'from_level': from_level,
                'to_level': to_level,
                'extra_inactive': extra_inactive,
                'extra_active': extra_active,
                'namespace': namespace
            })
        except:
            context = {"template": template}
        return context