def tree_info(items, features=None): """ Given a list of tree items, produces doubles of a tree item and a ``dict`` containing information about the tree structure around the item, with the following contents: new_level ``True`` if the current item is the start of a new level in the tree, ``False`` otherwise. closed_levels A list of levels which end after the current item. This will be an empty list if the next item is at the same level as the current item. Using this filter with unpacking in a ``{% for %}`` tag, you should have enough information about the tree structure to create a hierarchical representation of the tree. Example:: {% for genre,structure in genres|tree_info %} {% if tree.new_level %}<ul><li>{% else %}</li><li>{% endif %} {{ genre.name }} {% for level in tree.closed_levels %}</li></ul>{% endfor %} {% endfor %} """ kwargs = {} if features: feature_names = features.split(',') if 'ancestors' in feature_names: kwargs['ancestors'] = True return tree_item_iterator(items, **kwargs)
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['child_users_iter'] = None if self.request.user.has_perm('users.can_crud_all_child'): context['child_users_iter'] = tree_item_iterator( self.object.get_descendants()) return context
def menu_by_sub_tree(node, order_field, html): print 'menu_by_sub_tree->{0}'.format(node.name) if not node.is_leaf_node(): if not node.is_root_node(): html += ('<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">{0}<b class="caret"></b></a><ul class="dropdown-menu">'.format(node.name)) else: # root node html += '<ul class="nav nav-pills pull-right">' for i,s in tree_item_iterator(node.get_children().order_by(order_field)): html = MenuManager.menu_by_sub_tree(i, order_field, html) if not node.is_root_node(): html += '</ul>' else: html += '</ul></li>' else: # leaf node print <li></li> html += ('<li><a href="{0}">{1}</a></li>'.format(node.url, node.name)) return html # class NodeManager(): # # @staticmethod # def getNodes(): # print 'calling getNodes()...' # nodes = Node.objects.all() # return nodes
def __get_table_content(self): # Get presets tree in tree order presets_tree = OrderedDict() for preset_job, tree_info in tree_item_iterator(PresetJob.objects.all()): presets_tree[preset_job.id] = {'instance': preset_job, 'jobs': OrderedDict()} for job in self._jobs_qs: presets_tree[job.preset_id]['jobs'][job.id] = { 'instance': job, 'decisions': [], 'values': self.__get_job_values_row(job) } # Cut preset jobs branches without jobs on leaves if self.view.user.role == USER_ROLES[0][0]: presets_to_preserve = set() for preset_id in reversed(list(presets_tree)): parent_id = presets_tree[preset_id]['instance'].parent_id if presets_tree[preset_id]['jobs'] or preset_id in presets_to_preserve: presets_to_preserve.add(parent_id) else: del presets_tree[preset_id] # Initialize values dictionary for decision in self._decisions_qs: if decision.job.preset_id not in presets_tree or \ decision.job_id not in presets_tree[decision.job.preset_id]['jobs']: continue values_row = self._values_collector.get_decision_values_row(decision) presets_tree[decision.job.preset_id]['jobs'][decision.job_id]['decisions'].append([decision, values_row]) return presets_tree
def microsite(request, microsite): microsite = get_object_or_404(Microsite, slug=microsite) page_title = u"%s Home" % microsite.name breadcrumbs = [{"url": reverse("materials:microsite", kwargs=dict(microsite=microsite.slug)), "title": page_title}] query = SearchQuerySet().narrow("is_displayed:true") query = query.narrow("microsites:%i" % microsite.id) query = query.order_by("-rating") query = query.facet("indexed_topics").facet("keywords").facet("grade_levels").facet("course_material_types") items = [] results = query[0:8] for result in results: items.append(populate_item_from_search_result(result)) facets = query.facet_counts()["fields"] topics = [] topic_counts = dict(facets["indexed_topics"]) for topic, tree_info in tree_item_iterator(microsite.topics.all()): topic.count = topic_counts.get(str(topic.id), 0) topics.append((topic, tree_info)) grade_levels = [] grade_level_counts = dict(facets["grade_levels"]) for level in GradeLevel.objects.all(): level.count = grade_level_counts.get(str(level.id), 0) grade_levels.append(level) course_material_types = [] course_material_type_counts = dict(facets["course_material_types"]) for material_type in CourseMaterialType.objects.all(): material_type.count = course_material_type_counts.get(str(material_type.id), 0) course_material_types.append(material_type) keywords = query.count() and facets.get("keywords", []) or [] if len(keywords) > MAX_TOP_KEYWORDS: keywords = keywords[:MAX_TOP_KEYWORDS] keywords = get_tag_cloud(dict(keywords), 3, 0, 0) for keyword in keywords: name = get_name_from_slug(Keyword, keyword["slug"]) or \ get_name_from_slug(Tag, keyword["slug"]) or \ keyword["slug"] keyword["name"] = name featured_k12 = SearchQuerySet().filter(workflow_state=PUBLISHED_STATE, featured=True, grade_levels__in=(1, 2), microsites=microsite.id).order_by("-featured_on").load_all()[:3] featured_k12 = [r.object for r in featured_k12 if r] featured_highered = SearchQuerySet().filter(workflow_state=PUBLISHED_STATE, featured=True, grade_levels=3, microsites=microsite.id).order_by("-featured_on").load_all()[:3] featured_highered = [r.object for r in featured_highered if r] slides = Slide.objects.filter(microsite=microsite) resource_number = SearchQuerySet().filter(workflow_state=PUBLISHED_STATE, microsites=microsite.id).count() return direct_to_template(request, "materials/microsites/%s.html" % microsite.slug, locals())
def print_sub_tree(self, node, field_name): mark = self.get_mark() if not node.is_leaf_node(): self.level.append('+') if not node.is_root_node(): print '{0}{1}'.format(mark,node) for i,s in tree_item_iterator(node.get_children().order_by(field_name)): self.print_sub_tree(i, field_name) self.level.pop() else: print '{0}{1}'.format(mark,node)
def navigation(request): """Get all pages with one query, then aranges in a tree.""" pages = Page.objects.active().filter(in_navigation=True) if not request.user.is_authenticated(): pages = pages.filter(require_login=False) else: allpages = pages.filter(only_public=False) pages = list(allpages.filter(require_permission=False)) pages += list(get_objects_for_user(request.user, "page.can_view", allpages.filter(require_permission=True))) pages.sort(key=lambda p: (p.tree_id, p.lft)) return tree_item_iterator(pages)
def navigation(request): """Get all pages with one query, then aranges in a tree.""" pages = Page.objects.active().filter(in_navigation=True) if not request.user.is_authenticated(): pages = pages.filter(require_login=False) else: allpages = pages.filter(only_public=False) pages = list(allpages.filter(require_permission=False)) pages += list( get_objects_for_user(request.user, "page.can_view", allpages.filter(require_permission=True))) pages.sort(key=lambda p: (p.tree_id, p.lft)) return tree_item_iterator(pages)
def __get_table_content(self): # Get presets tree in tree order presets_tree = OrderedDict() for preset_job, tree_info in tree_item_iterator(PresetJob.objects.all()): presets_tree[preset_job.id] = {'instance': preset_job, 'jobs': OrderedDict()} for job in self._jobs_qs: presets_tree[job.preset_id]['jobs'][job.id] = { 'instance': job, 'decisions': [], 'values': self.__get_job_values_row(job) } # Initialize values dictionary for decision in self._decisions_qs: if decision.job_id not in presets_tree[decision.job.preset_id]['jobs']: continue values_row = self._values_collector.get_decision_values_row(decision) presets_tree[decision.job.preset_id]['jobs'][decision.job_id]['decisions'].append([decision, values_row]) return presets_tree
def green_browse(request): microsite = get_object_or_404(Microsite, slug="green") query = SearchQuerySet().narrow("is_displayed:true") query = query.narrow("microsites:%i" % microsite.id) query = query.facet("indexed_topics").facet("keywords").facet("grade_levels").facet("course_material_types") facets = query.facet_counts()["fields"] topics = [] topic_counts = dict(facets["indexed_topics"]) for topic, tree_info in tree_item_iterator(microsite.topics.all()): topic.count = topic_counts.get(str(topic.id), 0) topics.append((topic, tree_info)) grade_levels = [] grade_level_counts = dict(facets["grade_levels"]) for level in GradeLevel.objects.all(): level.count = grade_level_counts.get(str(level.id), 0) grade_levels.append(level) course_material_types = [] course_material_type_counts = dict(facets["course_material_types"]) for material_type in CourseMaterialType.objects.all(): material_type.count = course_material_type_counts.get(str(material_type.id), 0) course_material_types.append(material_type) keywords = query.count() and facets.get("keywords", []) or [] if len(keywords) > MAX_TOP_KEYWORDS: keywords = keywords[:MAX_TOP_KEYWORDS] keywords = get_tag_cloud(dict(keywords), 3, 0, 0) for keyword in keywords: name = get_name_from_slug(Keyword, keyword["slug"]) or \ get_name_from_slug(Tag, keyword["slug"]) or \ keyword["slug"] keyword["name"] = name query = SearchQuerySet().narrow("is_displayed:true") query = query.narrow("microsites:%i" % microsite.id) query = query.order_by("-published_on").load_all() recently_added = [r.object for r in query[:7]] return direct_to_template(request, "materials/microsites/green-browse.html", locals())
def as_python_tree(self): iterator = tree_item_iterator(self) first = True current = [] stack = [current] for row, infos in iterator: if infos["new_level"] and not first: stack.append(current) current = current[-1][1] current.append([row, []]) first = False for i in infos["closed_levels"]: if stack: current = stack.pop() return current
def get_menu_iterative(context, menu, menu_tree): user = context['request'].user children = tree_item_iterator(menu.get_descendants_by_user(user)) if children: for child, options in children: if user.is_staff or child.is_published(): menu_child = {} menu_child['name'] = child.name menu_child['slug'] = child.slug menu_child['url'] = child.get_absolute_url() new_level = options['new_level'] closed_levels = options['closed_levels'] if child.level in closed_levels: len_closed_levels = len(closed_levels) if child.level == 1: len_closed_levels -= 1 menu_child['end_level'] = range(len_closed_levels) else: menu_child['end_level'] = range(False) menu_child['new_level'] = new_level menu_tree.append(menu_child)
def menu_by_sub_tree(self, node, order_field, html): print 'menu_by_sub_tree->{0}'.format(node.name) if not node.is_leaf_node(): if not node.is_root_node(): html += ('<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">{0}<b class="caret"></b></a><ul class="dropdown-menu">'.format(node.name)) else: # root node html += '<ul class="nav nav-pills pull-right">' for i,s in tree_item_iterator(node.get_children().order_by(order_field)): html = self.menu_by_sub_tree(i, order_field, html) if not node.is_root_node(): html += '</ul>' else: html += '</ul></li>' else: # leaf node print <li></li> html += ('<li><a href="{0}">{1}</a></li>'.format(node.url, node.name)) return html
def process_request(self, request): # When working with multiple tenants, we want to shard the cache for # each of them. Use of the version is a nice way to do this as it will # prevent collisions while making the API consistent. v_kw = {} if hasattr(request, "tenant"): v_kw.setdefault("version", request.tenant.schema_name) # TODO write a cache backend that will do this automatically, and # contribute it back to django-tenant-schemas dehydrated = cache.get(DEHYDRATED_URLPATTERNS_KEY, [], **v_kw) if not dehydrated: logging.getLogger("newrelic.cache").debug("RECALCULATE URLCONF") # We need a secret set of account urls so we can bounce the user # here if the page is protected. As we haven't yet embedded our # url conf (we're in the middle of building it!) this will need # to be found using a reverse_lazy below. try: root = SitemapNode._tree_manager.root_nodes().first() except ObjectDoesNotExist: root = None dehydrated.append({ "route": "p/", "site": protect, "kwargs": { "node": root } }) enabled_nodes = SitemapNode._tree_manager.all() related_nodes = enabled_nodes.select_related("content_type") def has_disabled_ancestors(st): for ancestor in st["ancestors"]: if not ancestor.enabled: return True return False def get_absolute_url(n, st): assert not n.is_root_node() offset = 1 if st["ancestors"][0].slug == SITEMAP_ROOT else 0 paths = [ ancestor.slug for ancestor in st["ancestors"][offset:] ] if paths: return os.path.join(os.path.join(*paths), n.slug) return n.slug for node, struct in tree_item_iterator(related_nodes, True, lambda x: x): # Skip over nodes that they themselves or have disabled ancestors. if not node.enabled: logger.debug("%r is disabled, omit from urlconf", node) continue if has_disabled_ancestors(struct): logger.debug("%r has disabled ancestor, omit from urlconf", node) continue if node.is_root_node() and node.slug == SITEMAP_ROOT: part = "" elif node.is_root_node(): part = node.slug else: part = get_absolute_url(node, struct) if part and settings.APPEND_SLASH: part += "/" if (node.content_type is not None and node.content_type.model == "placeholder"): try: app = node.object.site(node) except (AttributeError, ImportError, ValueError): logger.exception( "Application is unavailable, disabling this node.") node.disable() else: pattern = { "route": part, "site": app, "kwargs": dict(node=node, **node.kwargs), "name": app.name, } # When nesting applications we need to ensure that any # root url is not clobbered by the patterns of the # parent application. In these cases, force them to the # top of the map. if (node.parent and node.parent.content_type and node.parent.content_type.model == "placeholder"): dehydrated.insert(0, pattern) else: dehydrated.append(pattern) elif node.object_id is None: dehydrated.append({ "route": part, "view": dispatch, "kwargs": dict(node=node, url=part), "name": f"folder_{node.pk}", }) else: dehydrated.append({ "route": part, "view": dispatch, "kwargs": dict(page_id=node.object_id, node=node, url=part), "name": f"page_{node.object_id if node.object_id else None}", }) cache.set( DEHYDRATED_URLPATTERNS_KEY, dehydrated, timeout=DEHYDRATED_URLPATTERNS_TIMEOUT, **v_kw, ) # Always start with the project wide ROOT_URLCONF and add our sitemap.xml view urlpatterns = [ path( "sitemap.xml", sitemap, {"sitemaps": { "nodes": NodeSitemap }}, name="sitemap", ), path("", include(settings.ROOT_URLCONF)), ] # Construct the cache of url pattern definitions. We are not keeping # the actual patterns, because pickling is problematic for the .url # instancemethod - instead we keep the skeleton and build it on the # fly from cache... rehydrating it ;) for node in dehydrated: try: pattern = path( node["route"], node["view"], node["kwargs"], name=node.get("name"), ) except KeyError: pattern = path( node["route"], node["site"].urls, node["kwargs"], name=node["site"].name, ) urlpatterns.append(pattern) # Create a new module on the fly and attach the rehydrated urlpatterns dynamic_urls = module_from_spec(ModuleSpec("dynamic_urls", None)) dynamic_urls.urlpatterns = urlpatterns # Attach the module to the request request.urlconf = dynamic_urls