def test_menu_nodes(self): """ Tests if all categories are present in the menu """ posts = self.get_posts() pages = self.get_pages() self.reload_urlconf() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url)) cache.clear() posts[0].categories.clear() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) self.assertTrue(posts[1].get_absolute_url(lang) in nodes_url)
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ pages = self.get_pages() posts = self.get_posts() self.reload_urlconf() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url)) cache.clear() posts[0].categories.clear() for lang in ('en', 'it'): with smart_override(lang): request = self.get_page_request(pages[1], self.user, pages[1].get_absolute_url(lang)) nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(posts[0].get_absolute_url(lang) in nodes_url) self.assertTrue(posts[1].get_absolute_url(lang) in nodes_url)
def test_admin_clear_menu(self): """ Tests that after changing apphook config menu structure the menu content is different: new value is taken immediately into account """ pages = self.get_pages() post = self._get_post(self._post_data[0]['en']) request = self.get_page_request(None, self.user, r'/en/page-two/') first_nodes = menu_pool.get_nodes(request) with pause_knocks(post): with self.login_user_context(self.user): data = dict(namespace='sample_app', app_title='app1', object_name='Blog') data['config-menu_structure'] = MENU_TYPE_NONE data['config-sitemap_changefreq'] = 'weekly' data['config-sitemap_priority'] = '0.5' request = self.post_request(pages[0], 'en', user=self.user, data=data) msg_mid = MessageMiddleware() msg_mid.process_request(request) config_admin = admin.site._registry[BlogConfig] response = config_admin.change_view(request, str(self.app_config_1.pk)) second_nodes = menu_pool.get_nodes(request) self.assertNotEqual(len(first_nodes), len(second_nodes))
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ post1, post2 = self.get_posts() tests = ( # view class, view kwarg, view object, category (PostDetailView, 'slug', post1, post1.categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(None, self.user, r'/en/blog/', edit=False) activate('en') with switch_language(obj, 'en'): view_obj = view_cls() view_obj.request = request view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) # check if selected menu node points to cat nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') found = False for node in nodes: if node.selected: self.assertEqual(node.url, cat.get_absolute_url()) found = True break self.assertTrue(found)
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ for lang in ('en', 'it'): request = self.get_page_request(None, self.user, r'/%s/blog/' % lang, edit=False) activate(lang) nodes = menu_pool.get_nodes(request, namespace='BlogCategoryMenu') nodes_copy = copy.deepcopy(nodes) for cat in self.cats: if not cat.has_translation(lang): continue with switch_language(cat, lang): # find in node list found = None for node in nodes_copy: if node.url == cat.get_absolute_url(): found = node break self.assertIsNotNone(found) nodes_copy.remove(found) self.assertEqual(node.id, cat.id) self.assertEqual(node.title, cat.name) # check that all categories were found in menu self.assertEqual(len(nodes_copy), 0)
def test_public_menu_anonymous_user(self): """ Anonymous user should only see the pages in the rendered menu that have no permissions assigned,directly or indirectly """ self._setup_user_groups() all_pages = self._setup_tree_pages() self._setup_view_restrictions() granted = ['page_a', 'page_c', 'page_c_a', 'page_c_b', 'page_d_a', 'page_d_b', 'page_d_c', 'page_d_d' ] self.assertGrantedVisibility(all_pages, granted) urls = self.get_url_dict(all_pages) user = AnonymousUser() request = self.get_request(user, urls['/en/']) nodes = menu_pool.get_nodes(request) self.assertEqual(len(nodes), 4) self.assertInMenu(urls["/en/"], user) self.assertInMenu(urls["/en/page_c/"], user) self.assertInMenu(urls["/en/page_c/page_c_a/"], user) self.assertInMenu(urls["/en/page_c/page_c_b/"], user) self.assertViewNotAllowed(urls["/en/page_b/"], user) self.assertNotInMenu(urls["/en/page_b/"], user) self.assertViewNotAllowed(urls["/en/page_d/"], user) self.assertNotInMenu(urls["/en/page_d/"], user)
def get_context(self, context, template, name ): try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } all_nodes = menu_pool.get_nodes(request) nodes = menu_pool.get_nodes_by_attribute(all_nodes, 'type', 'family') for node in nodes: if (node.ancestor or node.selected) and node.attr['type'] == 'family': break if node.descendant: # We must be at a designer node.selected = True # This must be the first family, so select it break if node.selected: # We're at a family or designer, so automatically select the first stamp node.children[0].selected = True try: context = { 'children': node.children } except: context = { 'template': template} return context
def get_context(self, context, template, name ): try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } all_nodes = menu_pool.get_nodes(request) nodes = menu_pool.get_nodes_by_attribute( all_nodes, 'type', 'designer' ) for node in all_nodes: # If we're at the root level, don't bother getting children if node.selected and node.level < 2: context = { 'template': template} return context for node in nodes: if node.selected and node.attr['type'] == 'designer': # Set first family to be selected node.children[0].selected = True break if node.ancestor and node.attr['type'] == 'designer': break try: context = { 'children': node.children } except: context = { 'template': template} return context
def show_sub_menu(context, levels=100, template="menu/sub_menu.html"): """ show the sub menu of the current nav-node. -levels: how many levels deep -temlplate: template used to render the navigation """ 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
def get_context(self, context, root_id, namespace ): try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } all_nodes = menu_pool.get_nodes(request, namespace, root_id ) nodes = menu_pool.get_nodes_by_attribute(all_nodes, 'type', 'stamp') current_index = None for node in nodes: assert node.attr['type'] == 'stamp' for node in nodes: if node.selected or node.descendant: current_index = nodes.index(node) break assert current_index != None try: next_link = nodes[current_index + 1] except IndexError: next_link = ((node.parent).parent).parent context['next'] = next_link context['prev'] = None return context
def show_sub_menu(context, levels=100, template="menu/sub_menu.html"): """ show the sub menu of the current nav-node. -levels: how many levels deep -temlplate: template used to render the navigation """ 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
def render(self, context, instance, placeholder): try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return _("There is no `request` object in the context.") root_page = instance.root root_page_url = root_page.get_absolute_url() from_level = instance.start_level to_level = instance.depth nodes = menu_pool.get_nodes(request) children = list() root_node = None # Find the root node for node in nodes: if not root_node and node.url == root_page_url: root_node = node if root_node: if instance.include_root: children += (root_node, ) else: children += root_node.children context.update({'MenuItems': children}) return context
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
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ posts = self.get_posts() pages = self.get_pages() tests = ( # view class, view kwarg, view object, category (PostDetailView, "slug", posts[0], posts[0].categories.first()), (CategoryEntriesView, "category", self.cats[2], self.cats[2]), ) for view_cls, kwarg, obj, cat in tests: request = self.get_page_request(pages[1], self.user, path=obj.get_absolute_url()) with smart_override("en"): with switch_language(obj, "en"): view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) # check if selected menu node points to cat nodes = menu_pool.get_nodes(request, namespace="BlogCategoryMenu") found = False for node in nodes: if node.selected: self.assertEqual(node.url, obj.get_absolute_url()) found = True break self.assertTrue(found)
def render(self, context, instance, placeholder): try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return "There is no `request` object in the context." root_page = instance.root root_page_url = root_page.get_absolute_url() from_level = instance.start_level to_level = instance.depth nodes = menu_pool.get_nodes(request) children = list() root_node = None # Find the root node for node in nodes: if not root_node and node.url == root_page_url: root_node = node if root_node: if instance.include_root : children += (root_node, ) else: children += root_node.children context.update({ 'MenuItems' : children, }) return context
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 test_public_menu_anonymous_user(self): """ Anonymous user should only see the pages in the rendered menu that have no permissions assigned,directly or indirectly """ self._setup_user_groups() all_pages = self._setup_tree_pages() self._setup_view_restrictions() granted = [ 'page_a', 'page_c', 'page_c_a', 'page_c_b', 'page_d_a', 'page_d_b', 'page_d_c', 'page_d_d' ] self.assertGrantedVisibility(all_pages, granted) urls = self.get_url_dict(all_pages) user = AnonymousUser() request = self.get_request(user, urls['/en/']) nodes = menu_pool.get_nodes(request) self.assertEqual(len(nodes), 4) self.assertInMenu(urls["/en/"], user) self.assertInMenu(urls["/en/page_c/"], user) self.assertInMenu(urls["/en/page_c/page_c_a/"], user) self.assertInMenu(urls["/en/page_c/page_c_b/"], user) self.assertViewNotAllowed(urls["/en/page_b/"], user) self.assertNotInMenu(urls["/en/page_b/"], user) self.assertViewNotAllowed(urls["/en/page_d/"], user) self.assertNotInMenu(urls["/en/page_d/"], user)
def cms_section(request): nodes = menu_pool.get_nodes(request) if nodes: menu_root = nodes[0] if 'soft_root' in menu_root.attr: return {'section_root': {'title': menu_root.title}} return {}
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 footer_menus(context): request = context['request'] all_nodes = menu_pool.get_nodes(request, site_id=request.site.id) # level 0 is confusingly the home page and second level pages nodes = [node for node in all_nodes if node.level == 0] context['second_level_nodes'] = nodes[1:] # chop off home page return context
def kipp_sub_menu(context, template="menu/sub_menu.html"): 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) parent_node = None children = [] for node in nodes: if (node.level == 1) or (node.get_attribute("reverse_id")=="get-involved"): if (node.ancestor) or (node.selected): parent_node = node if parent_node is None: pass else: children = parent_node.children context.update({'children':children, 'template':template, 'from_level':0, 'to_level':0, 'extra_inactive':0, 'extra_active':0 }) return context
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
def get_context(self, context, template, namespace, root_id, offset, limit, 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) children = children[offset:offset + limit] context.update({'children': children, 'template': template}) return context
def get_queryset(self): site = get_current_site(self.request) if self.action == 'menu': return menu_pool.get_nodes(self.request, site_id=site.pk) if use_draft(self.request): return Page.objects.drafts().on_site(site=site).distinct() else: return Page.objects.public().on_site(site=site).distinct()
def _get_context_internal(self, context, from_level, to_level, extra_inactive, extra_active, max_count, filter_opt, template, namespace, root_id, next_page): trim_children = (filter_opt & FILTER_TRIM_CHILDREN != 0) try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return {'template': 'menu/empty.html'} has_root_node = False if next_page: children = next_page.children else: #new menu... get all the data so we can save a lot of queries 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: root_node = node = id_nodes[0] has_root_node = True new_nodes = node.children for n in new_nodes: n.parent = None from_level += node.level + 1 to_level += node.level + 1 else: new_nodes = [] nodes = new_nodes children = cut_levels(nodes, from_level, to_level, extra_inactive, extra_active, trim_children) children = menu_pool.apply_modifiers(children, request, namespace, root_id, post_cut=True) if filter_opt & FILTER_INTER: children = [node for node in children if node.is_leaf_node] elif filter_opt & FILTER_LEAF: children = [node for node in children if not node.is_leaf_node] # only return the top ``max_count`` ones if specified if max_count != -1: children = children[:max_count] try: context.update({'children':children, 'template':template, 'from_level':from_level, 'to_level':to_level, 'extra_inactive':extra_inactive, 'extra_active':extra_active, 'max_count':max_count, 'filter_opt':filter_opt, 'namespace':namespace}) if has_root_node: context['root_node'] = root_node except: context = {"template":template} return context
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'} nodes = menu_pool.get_nodes(request) 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: child.parent = None 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_pool.apply_modifiers( [node], request, post_cut=True ) else: 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
def test_get_menus(self): """ Check that menus are dynamically loaded according to the different page the apphook is attached to """ titles = self.create_base_structure('VariableUrlsApp', ['en', 'de']) titles[0].page.reverse_id = 'page1' titles[0].page.save() cache.clear() self.reload_urls() menu_pool.discover_menus() cache.clear() request = self.get_request('/') nodes = menu_pool.get_nodes(request) nodes_urls = [node.url for node in nodes] self.assertTrue(reverse('sample-account') in nodes_urls) self.assertFalse('/en/child_page/page2/' in nodes_urls) self.reload_urls() self.apphook_clear() cache.clear() self.reload_urls() page2 = create_page('page2', 'nav_playground.html', 'en', created_by=self.superuser, published=True, parent=titles[0].page.get_draft_object().parent, in_navigation=True, apphook='VariableUrlsApp', reverse_id='page2') create_title('de', 'de_title', page2, slug='slug') page2.publish('de') request = self.get_request('/page2/') nodes = menu_pool.get_nodes(request) nodes_urls = [node.url for node in nodes] self.assertTrue(reverse('sample-account') in nodes_urls) self.assertTrue(reverse('sample2-root') in nodes_urls) self.assertTrue('/static/fresh/' in nodes_urls) self.apphook_clear()
def assertNotInMenu(self, page, user): request = self.get_request(user, page) nodes = menu_pool.get_nodes(request) target_url = page.get_absolute_url() found_in_menu = False for node in nodes: if node.get_absolute_url() == target_url: found_in_menu = True break self.assertFalse(found_in_menu)
def test_public_pages_anonymous_norestrictions(self): """ All pages are visible to an anonymous user """ all_pages = self._setup_tree_pages() request = self.get_request() visible_page_ids = get_visible_pages(request, all_pages, self.site) self.assertEqual(len(all_pages), len(visible_page_ids)) nodes = menu_pool.get_nodes(request) self.assertEqual(len(nodes), len(all_pages))
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'} nodes = menu_pool.get_nodes(request) 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: child.parent = None 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_pool.apply_modifiers([node], request, post_cut=True) else: 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
def serialize_navigation(self, request): nodes = menu_pool.get_nodes(request) cleaned = [] for node in nodes: node.children = None node.parent = None cleaned.append(node.__dict__) return json.dumps(cleaned, cls=LazyEncoder)
def _navigation_preview(self, request, nav_node): if not request or not nav_node: return '' nodes = menu_pool.get_nodes(request, None, None) nodes = cut_levels(nodes, 0, 1, 1, 100) nodes = menu_pool.apply_modifiers( nodes, request, None, None, post_cut=True) output = [] self._get_nodes(request, nodes, nav_node.menu_id, output) html_preview = ''.join(output) if 'current-node' not in html_preview: return "" return html_preview
def test_menu_nodes(self): """ Tests if all categories are present in the menu """ self.get_posts() self.get_pages() for lang in ("en", "it"): request = self.get_page_request(None, self.user, r"/%s/page-two/" % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request, namespace="BlogCategoryMenu") nodes_url = set([node.url for node in nodes]) cats_url = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) self.assertTrue(cats_url.issubset(nodes_url))
def get_context(self, context, family, root_id, namespace ): try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } # Fetch all nodes of all types all_nodes = menu_pool.get_nodes(request, namespace, root_id ) # Fetch families nodes = menu_pool.get_nodes_by_attribute(all_nodes, 'type', 'family') current_index = None for node in nodes: if node.descendant: if node.parent.attr['type'] == 'designer' and node.parent.selected: # We're at the designer level, so make first descendant the selected node current_index = nodes.index(node) break else: # We're at the root index, so just return with first family and arbitrary previoous context['next'] = nodes[0] context['prev'] = node.parent.parent.parent # This happens to be /resources/ return context if node.selected or node.ancestor: current_index = nodes.index(node) break print current_index assert current_index != None # This is done after selection, as the selected node can be invisible for n in nodes: # Cut out any invisible nodes (this could have weird behavior) if not n.visible: nodes.remove(n) try: next_link = nodes[current_index + 1] except IndexError: next_link = (node.parent).parent prev_link = nodes[current_index - 1] if current_index == 0: prev_link = (node.parent).parent context['next'] = next_link context['prev'] = prev_link return context
def show_menu(context, from_level=0, to_level=100, extra_inactive=0, extra_active=100, template="menu/menu.html", namespace=None, root_id=None, next_page=None, ): """ 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 """ 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 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] new_nodes = node.children for n in new_nodes: n.parent = None from_level += node.level + 1 to_level += node.level + 1 else: new_nodes = [] nodes = new_nodes 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) 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
def get_context(self, context, template, name ): try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } nodes = menu_pool.get_nodes(request) nodes = menu_pool.get_nodes_by_attribute( nodes, 'type', name ) try: context = { 'children': nodes } except: context = { 'template': template} return context
def get_or_set_cache(request, cache_key, model=CMSArticle, seconds_to_cache=60*30, **kwargs): """Cache key or get query Gets the query from cache or returns the queryset. Example: article = get_or_set_cache(key, CMSArticle, seconds_to_cache=60*30, slug='slug') """ q = cache.get(cache_key) if not q: q = menu_pool.get_nodes(request) #cache.set(cache_key, q, seconds_to_cache) return q
def get_context(self, context, template, from_level, to_level, root_id, namespace ): try: try: request = context['request'] except KeyError: return { 'template': 'menu/empty.html' } nodes = menu_pool.get_nodes( request, namespace, root_id ) current_index = None root_nodes = [] for node in nodes: if node.level == 0: root_nodes.append(node) for node in root_nodes: assert node.level == 0 # There should be only root level nodes if node.selected or node.ancestor: current_index = root_nodes.index(node) assert current_index != None break # This is done after selection, as the selected node can be invisible for n in root_nodes: # Cut out any invisible nodes (this could have weird behavior) if not n.visible: root_nodes.remove(n) try: # Next Link next_link = root_nodes[current_index + 1] except IndexError: next_link = None try: # Previous Link prev_link = root_nodes[current_index - 1] if current_index == 0: raise IndexError except IndexError: prev_link = None try: context = {'next': next_link, 'prev': prev_link} except: context = { 'template': template} return context except Exception, e: pass
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 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 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_pool.apply_modifiers(children, request, namespace, root_id, post_cut=True) 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
def get_menu_titles(self, user): # o RequestFactory é um troço bem simples que não lida com sessões ou # autenticação. Precisa colocar o atributo do usuário na mão request = self.factory.get('/') request.user = user # Isso aqui é uma lista (gênio) menu_nodes = menu_pool.get_nodes(request) # a função get_menu_title retorna um objeto do tipo # django.utils.functional.__proxy__, que nada mais é do que uma string # que foi passada pro gettext como _('string em português'). Pra ela # virar uma "string de verdade", precisa chamar unicode(proxy). Mas # como em python 3 não existe o tipo "unicode", eu uso six.text_type, # que é str em py3 ou unicode em py2 e fica tudo certo menu_title_proxies = [n.get_menu_title() for n in menu_nodes] menu_titles = map(six.text_type, menu_title_proxies) return menu_titles
def get_context(self, context, start_level, template, only_visible): try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return {'template': 'cms/content.html'} if not (isinstance(start_level, int) or start_level.isdigit()): only_visible = template template = start_level start_level = 0 try: only_visible = bool(int(only_visible)) except: only_visible = bool(only_visible) ancestors = [] nodes = menu_pool.get_nodes(request, breadcrumb=True) # Find home home = None root_url = unquote(reverse("pages-root")) home = next( (node for node in nodes if node.get_absolute_url() == root_url), None) # Find selected selected = None selected = next((node for node in nodes if node.selected), None) if selected and selected != home: node = selected while node: if node.visible or not only_visible: ancestors.append(node) node = node.parent if not ancestors or (ancestors and ancestors[-1] != home) and home: ancestors.append(home) ancestors.reverse() if len(ancestors) >= start_level: ancestors = ancestors[start_level:] else: ancestors = [] context['ancestors'] = ancestors context['template'] = template return context
def cache_nodes(request, queryset): """ Build a page of one category's article nodes """ if queryset: lang = get_language() site_id = Site.objects.get_current().pk prefix = getattr(settings, "CMS_CACHE_PREFIX", "menu_cache_") key = "%smenu_nodes_%s_%s" % (prefix, lang, site_id) parent_node = None # build article_nodes from queryset in menu cache article_nodes = [] for article in queryset: article_nodes.append(NavigationNode( article.title, article.url, article.menu.menuid, article.menu.parent, ) ) # get the original cache nodes. if blank, get the whole nodes. if # article_nodes are already in cache nodes, return. cached_nodes = cache.get(key, None) if cached_nodes: str_cached_nodes = str(cached_nodes) if str(article_nodes[0]) in str_cached_nodes: return else: cached_nodes = menu_pool.get_nodes(request) parent_node = category_node(article, cached_nodes) # add parent_node to the article node and save into cached_node for node in article_nodes: node.parent = parent_node node.namespace = getattr(parent_node, 'namespace', None) cached_nodes.append(node) duration = getattr(settings, "MENU_CACHE_DURATION", 60*60) cache.set(key, cached_nodes, duration) else: return
def _get_content(request): site = get_current_site(request) nav_links = [] if conf.ERROR_PAGE_CMS_LINKS: try: from menus.menu_pool import menu_pool from menus.templatetags.menu_tags import cut_levels from cms.models import Page try: for page in cut_levels( menu_pool.get_nodes(request, site_id=site.id), 0, 1, 0, 1000): nav_links.append([ page.get_absolute_url(), page.get_menu_title(), ]) except AttributeError: # if no user in request for page in Page.objects.on_site(site).public(): if page.is_root_node(): nav_links.append([ page.get_absolute_url(), page.get_title(), ]) except ImportError: pass # django-cms is not installed if len(nav_links) == 0: nav_links = conf.ERROR_PAGE_NAV_LINKS return RequestContext( request, { 'site': site, 'year': datetime.datetime.now().year, 'theme_name': conf.ERROR_PAGE_THEME, 'theme_color': conf.ERROR_PAGE_THEME_COLOR, 'theme_static_url': conf.ERROR_PAGE_THEME_STATIC_URL, 'logo_url': conf.ERROR_PAGE_LOGO_URL, 'nav_links': nav_links, 'social_links': conf.ERROR_PAGE_SOCIAL_LINKS, 'search_action': conf.ERROR_PAGE_SEARCH_ACTION, 'search_method': conf.ERROR_PAGE_SEARCH_METHOD, 'search_param': conf.ERROR_PAGE_SEARCH_PARAM, })
def show_breadcrumb(context, start_level=0, template="menu/breadcrumb.html", only_visible=True): """ Shows the breadcrumb from the node that has the same url as the current request - start level: after which level should the breadcrumb start? 0=home - template: template used to render the breadcrumb """ try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return {'template': 'cms/content.html'} ancestors = [] nodes = menu_pool.get_nodes(request, breadcrumb=True) selected = None home = None for node in nodes: if node.selected: selected = node # find home: TODO: maybe home is not on "/"? if node.get_absolute_url() == "/": home = node if selected and selected != home: n = selected while n: if n.visible or not only_visible: ancestors.append(n) n = n.parent if not ancestors or (ancestors and ancestors[-1] != home) and home: ancestors.append(home) ancestors.reverse() if len(ancestors) >= start_level: ancestors = ancestors[start_level:] else: ancestors = [] context.update({'ancestors': ancestors, 'template': template}) return context
def test_15_empty_menu(self): Page.objects.all().delete() request = self.get_request() nodes = menu_pool.get_nodes(request) context = self.get_context() nodes = show_menu(context, 0, 100, 100, 100)['children']
def __init__(self, request, *args, **kwargs): super(SubmenuPreviewForm, self).__init__(*args, **kwargs) self.fields['active_page'].choices = [(n.get_absolute_url(), mark_safe(u'%s%s' % (' '* n.level, n.title))) for n in menu_pool.get_nodes(request)]
def test_menu_options(self): """ Tests menu structure based on menu_structure configuration """ self.get_pages() posts = self.get_posts() cats_url = {} posts_url = {} languages = ('en', 'it') for lang in languages: with smart_override(lang): cats_url[lang] = set([cat.get_absolute_url() for cat in self.cats if cat.has_translation(lang)]) posts_url[lang] = set([post.get_absolute_url(lang) for post in posts if post.has_translation(lang) and post.app_config == self.app_config_1]) # No item in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_NONE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Only posts in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_POSTS self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertFalse(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url)) # Only categories in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertFalse(posts_url[lang].issubset(nodes_url)) # Both types in the menu self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() cache.clear() for lang in languages: request = self.get_page_request(None, self.user, r'/%s/page-two/' % lang) with smart_override(lang): nodes = menu_pool.get_nodes(request) nodes_url = set([node.url for node in nodes]) self.assertTrue(cats_url[lang].issubset(nodes_url)) self.assertTrue(posts_url[lang].issubset(nodes_url))
def test_modifier(self): """ Tests if correct category is selected in the menu according to context (view object) """ pages = self.get_pages() posts = self.get_posts() tests = ( # view class, view kwarg, view object, category (PostDetailView, 'slug', posts[0], posts[0].categories.first()), (CategoryEntriesView, 'category', self.cats[2], self.cats[2]) ) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(obj.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_CATEGORIES self.app_config_1.save() for view_cls, kwarg, obj, cat in tests: with smart_override('en'): with switch_language(obj, 'en'): request = self.get_page_request( pages[1], self.user, path=obj.get_absolute_url() ) cache.clear() menu_pool.clear(all=True) view_obj = view_cls() view_obj.request = request view_obj.namespace, view_obj.config = get_app_instance(request) view_obj.app_config = self.app_config_1 view_obj.kwargs = {kwarg: obj.slug} view_obj.get(request) view_obj.get_context_data() # check if selected menu node points to cat nodes = menu_pool.get_nodes(request) found = [] for node in nodes: if node.selected: found.append(node.get_absolute_url()) self.assertTrue(cat.get_absolute_url() in found) self.app_config_1.app_data.config.menu_structure = MENU_TYPE_COMPLETE self.app_config_1.save()
def show_menu( context, from_level=0, to_level=100, extra_inactive=0, extra_active=100, template="menu/menu.html", namespace=None, root_id=None, next_page=None, ): """ 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 """ 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 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] new_nodes = node.children for n in new_nodes: n.parent = None from_level += node.level + 1 to_level += node.level + 1 else: new_nodes = [] nodes = new_nodes 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) 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
def get_nodes(self, menu_pool, request): try: nodes = menu_pool.get_renderer(request).get_nodes() except AttributeError: nodes = menu_pool.get_nodes(request) return nodes