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 EasyMapTag(InclusionTag): """ The syntax: {% easy_map <address> [<width> <height>] [<zoom>] [using <template_name>] %} The "address" parameter can be an ``easy_maps.Address`` instance or a string describing it. If an address is not found a new entry is created in the database. """ name = 'easy_map' template = 'easy_maps/map.html' options = Options( Argument('address', resolve=True, required=True), IntegerArgument('width', required=False, default=None), IntegerArgument('height', required=False, default=None), IntegerArgument('zoom', required=False, default=None), 'using', Argument('template_name', default=None, required=False), ) def render_tag(self, context, **kwargs): params = dict((k, v) for k, v in kwargs.items() if v and k != 'template_name') if 'address' in params and (len(params) == 2 or len(params) > 4): raise template.TemplateSyntaxError( "easy_map tag has the following syntax: " "{% easy_map <address> [<width> <height>] " "[zoom] [using <template_name>] %}" ) if settings.EASY_MAPS_GOOGLE_MAPS_API_KEY is None: raise ImproperlyConfigured( "easy_map tag requires EASY_MAPS_GOOGLE_MAPS_API_KEY to be " "set in global settings because of the restrictions " "introduced in Google Maps API v3 by Google, Inc." ) return super(EasyMapTag, self).render_tag(context, **kwargs) def get_template(self, context, **kwargs): return kwargs.get('template_name', None) or self.template def get_context(self, context, **kwargs): kwargs['map'] = parse_address(kwargs.pop('address')) kwargs['lat'] = kwargs['map'].latitude kwargs['lng'] = kwargs['map'].longitude kwargs['width'] = kwargs.get('width', None) or 320 kwargs['height'] = kwargs.get('height', None) or 240 kwargs['zoom'] = kwargs.get('zoom', None) or 16 kwargs['api_key'] = settings.EASY_MAPS_GOOGLE_MAPS_API_KEY return kwargs
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']), )
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 ShowMenuBelowId(ShowMenu): name = 'show_menu_below_id' options = Options( Argument('root_id', default=None, required=False), 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), Argument('template', default='menu/menu.html', required=False), Argument('namespace', default=None, required=False), 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)
class EasyMapTag(InclusionTag): """ The syntax: {% easy_map <address> [<width> <height>] [<zoom>] [using <template_name>] %} The "address" parameter can be an ``easy_maps.Address`` instance or a string describing it. If an address is not found a new entry is created in the database. """ name = 'easy_map' template = 'easy_maps/map.html' options = Options( Argument('address', resolve=True, required=True), IntegerArgument('width', required=False, default=None), IntegerArgument('height', required=False, default=None), IntegerArgument('zoom', required=False, default=16), 'using', Argument('template_name', default=None, required=False), ) def render_tag(self, context, **kwargs): params = dict((k, v) for k, v in kwargs.items() if v is not None) if len(params.keys()) == 3 or len(params.keys()) > 5: raise template.TemplateSyntaxError( "easy_map tag has the following syntax: " "{% easy_map <address> [<width> <height>] [zoom] [using <template_name>] %}" ) return super(EasyMapTag, self).render_tag(context, **kwargs) def get_template(self, context, **kwargs): return kwargs.get('template_name', None) or self.template def parse_address(self, address=None): if isinstance(address, Address): return address if not address: return Address(latitude=CENTER[0], longitude=CENTER[1]) else: return Address.objects.get_or_create(address=address)[0] raise NotImplementedError def get_context(self, context, **kwargs): kwargs.update({'map': self.parse_address(kwargs.pop('address'))}) return kwargs
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
class EasyMapTag(InclusionTag): """ The syntax: {% easy_map <address> [<width> <height>] [<zoom>] [using <template_name>] %} The "address" parameter can be an ``easy_maps.Address`` instance or a string describing it. If an address is not found a new entry is created in the database. """ name = "easy_map" template = "easy_maps/map.html" options = Options( Argument("address", resolve=True, required=True), Argument("width", required=False, default=None), Argument("height", required=False, default=None), IntegerArgument("zoom", required=False, default=None), "using", Argument("template_name", default=None, required=False), ) def render_tag(self, context, **kwargs): params = dict((k, v) for k, v in kwargs.items() if v and k not in ["template_name"]) if "address" in params and (len(params) == 2 or len(params) > 4): raise template.TemplateSyntaxError( "easy_map tag has the following syntax: " "{% easy_map <address> [<width> <height>] [zoom] [using <template_name>] %}" ) if settings.EASY_MAPS_GOOGLE_KEY is None: raise ImproperlyConfigured( "easy_map tag requires EASY_MAPS_GOOGLE_KEY to be set in global settings " "because of the restrictions introduced in Google Maps API v3 by Google, Inc." ) return super(EasyMapTag, self).render_tag(context, **kwargs) def get_template(self, context, **kwargs): return kwargs.get("template_name", None) or self.template def get_context(self, context, **kwargs): kwargs.update({"map": parse_address(kwargs.pop("address"))}) if not kwargs.get("zoom", None): kwargs["zoom"] = settings.EASY_MAPS_ZOOM # default value kwargs["language"] = settings.EASY_MAPS_LANGUAGE kwargs[ "api_key"] = settings.EASY_MAPS_GOOGLE_KEY or settings.EASY_MAPS_GOOGLE_MAPS_API_KEY return kwargs
class MapTag(InclusionTag): """ The syntax: {% map <lat> <lng> [<width> <height> <zoom>] %} """ name = 'map' template = 'easy_maps/map.html' options = Options( Argument('lat', resolve=True, required=True), Argument('lng', resolve=True, required=True), Argument('set_marker', default=False, resolve=True, required=False), IntegerArgument('width', required=False, default=320), IntegerArgument('height', required=False, default=240), IntegerArgument('zoom', required=False, default=18), 'using', Argument('template_name', default=None, required=False), ) def render_tag(self, context, **kwargs): if settings.EASY_MAPS_GOOGLE_MAPS_API_KEY is None: raise ImproperlyConfigured( "easy_map tag requires EASY_MAPS_GOOGLE_MAPS_API_KEY to be " "set in global settings because of the restrictions " "introduced in Google Maps API v3 by Google, Inc.") return super(MapTag, self).render_tag(context, **kwargs) def get_template(self, context, **kwargs): return kwargs.get('template_name', None) or self.template def get_context(self, context, **kwargs): kwargs['api_key'] = settings.EASY_MAPS_GOOGLE_MAPS_API_KEY return kwargs
class RenderMenu(InclusionTag): """ Renders children of given menu to given depth. """ name = "render_menu" template = "amenu/render_menu.html" options = Options( Argument('page', required=True), IntegerArgument('depth', required=True), ) def get_context(self, context, page, depth): if depth is not 0: context['depth'] = depth - 1 context['pages'] = page.get_children() else: context = None return context
class ShowSubMenu(InclusionTag): """ show the sub menu of the current nav-node. -levels: how many levels deep -temlplate: template used to render the navigation """ name = 'show_sub_menu' template = 'menu/dummy.html' options = Options( IntegerArgument('levels', default=100, required=False), Argument('template', default='menu/sub_menu.html', required=False), ) def get_context(self, context, levels, 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'} nodes = menu_pool.get_nodes(request) children = [] for node in nodes: if node.selected: cut_after(node, levels, []) children = node.children for child in children: child.parent = None children = menu_pool.apply_modifiers(children, request, post_cut=True) context.update({ 'children': children, 'template': template, 'from_level': 0, 'to_level': 0, 'extra_inactive': 0, 'extra_active': 0 }) return context
class RecentActions(InclusionTag): name = 'thadminjones_recentactions' template = 'thadminjones/recentactions.html' options = Options( IntegerArgument('maxnum', default=10, required=False, resolve=True), ) def get_context(self, context, maxnum, **kwargs): request = context['request'] if MaybeFail(request, context)(): return {} root_url = AdminHelper(request).get_index_url() def get_log_entries(user_id, maxnum, admin_root): """ This exists because LogEntry has a stupid bloody get_absolute_url() in < 1.6 """ entries = (LogEntry.objects.filter( user__id__exact=user_id).exclude( action_flag=DELETION).select_related( 'content_type', 'user')) for entry in entries[:maxnum]: existing_url = entry.get_admin_url() if not existing_url.startswith(admin_root): real_url = '/%s/%s/' % (admin_root, existing_url) entry.get_absolute_url = re.sub( pattern=multiple_slashes_re, repl='/', string=real_url) else: entry.get_absolute_url = existing_url yield entry entries = get_log_entries(user_id=request.user.pk, maxnum=maxnum, admin_root=root_url) return { 'admin_log': list(entries), }
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 ShowSubMenu(InclusionTag): """ show the sub menu of the current nav-node. - levels: how many levels deep - root_level: the level to start the menu at - nephews: the level of descendants of siblings (nephews) to show - template: template used to render the navigation """ name = 'show_sub_menu' template = 'menu/dummy.html' options = Options( IntegerArgument('levels', default=100, required=False), Argument('root_level', default=None, required=False), IntegerArgument('nephews', default=100, required=False), Argument('template', default='menu/sub_menu.html', required=False), ) def get_context(self, context, levels, root_level, nephews, template): # Django 1.4 doesn't accept 'None' as a tag value and resolve to '' # So we need to force it to None again if not root_level and root_level != 0: root_level = None 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) nodes = menu_renderer.get_nodes() children = [] # adjust root_level so we cut before the specified level, not after include_root = False if root_level is not None and root_level > 0: root_level -= 1 elif root_level is not None and root_level == 0: include_root = True for node in nodes: if root_level is None: if node.selected: # if no root_level specified, set it to the selected nodes level root_level = node.level # is this the ancestor of current selected node at the root level? is_root_ancestor = (node.ancestor and node.level == root_level) # is a node selected on the root_level specified root_selected = (node.selected and node.level == root_level) if is_root_ancestor or root_selected: cut_after(node, levels, []) children = node.children for child in children: if child.sibling: cut_after(child, nephews, []) # if root_level was 0 we need to give the menu the entire tree # not just the children if include_root: children = menu_renderer.apply_modifiers([node], post_cut=True) else: children = menu_renderer.apply_modifiers(children, post_cut=True) context['children'] = children context['template'] = template context['from_level'] = 0 context['to_level'] = 0 context['extra_inactive'] = 0 context['extra_active'] = 0 return context
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
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 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
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
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