def render(self, context): book = self.book.resolve(context) request = self.request.resolve(context) if request.user.is_superuser: tree_query_set = Page.objects \ .select_related('book') \ .filter(book__pk=book.id) else: cache_key = 'book.templatetags.book_tags.book_toc({})'.format(book.id) cache_time = settings.CACHE_TIME_VERY_SHORT tree_query_set = cache.get(cache_key) if not tree_query_set: try: tree_query_set = Page.objects \ .select_related('book') \ .filter(book__slug=book.slug, status=Page.STATUS_CHOICES.public) cache.set(cache_key, tree_query_set, cache_time) except Page.DoesNotExist: pass roots = get_cached_trees(tree_query_set) nodes = [self._render_category(context, category) for category in roots] return ''.join(nodes)
def __init__(self, model_class, node_id=None, attrs=(), extract_data_fn=False): """ Init the Builder instance. :param model_class: MPTTModel subclass :keyword node_id: the ID of tree node, root node by default :keyword extract_data_fn: the data extractor """ assert issubclass(model_class, MPTTModel), \ 'The parameter "model_class" is invalid' self.model_class = model_class if node_id: try: self.root_node = model_class.objects.get(pk=node_id) except ObjectDoesNotExist: raise 'There is no such node with id=<{0}>'.format(node_id) else: self.root_node = None self.attrs = attrs if attrs else type(self).default_attrs if extract_data_fn and callable(extract_data_fn): self.extract_data_fn = extract_data_fn else: self.extract_data_fn = self.default_extract_data self._root_children = get_cached_trees( model_class.objects.all() )
def render(self, context): roots = get_cached_trees(self.tree_query_set) nodes = [ self._render_category(context, category) for category in roots ] return ''.join(nodes)
def get_location_list(show_reserved=True): """Return a list of pseudo-serialized Locations. `show_reserved`: if True, show locations with id > 100. """ locations = [] location_list = models.Location.objects.all() roots = get_cached_trees(location_list) for root in roots: # Do not list the default location if root.id == 0: continue if show_reserved is False and root.id < 100: continue locations.append({ "sequence": [root.name], "id": root.id, "parent": None, "rescue_bag": root.is_rescue_bag }) children = root.get_children() if children: locations += location_iterator([root.name], children, root.id) return locations
def maintain_integrity_full_code(sender, instance: Account, update_fields=None, **kwargs): print(f"UPDATE_FIELDS: {update_fields}") assert sender is Account if kwargs.get('raw', False): return if update_fields is None or 'code' in update_fields: # WARNING: YOU ARE NOW ENTERING THE 3AM QUERY OPTIMIZATION ZONE # Avoid queries on get_children/get_ancestors by caching the entire subtree. descendants = instance.get_descendants(include_self=True) [cached_account_tree] = mptt_utils.get_cached_trees(descendants) # type: Account # By default, Django auto-commits, meaning it will hit the database once for # each call to save. By updating full_code's in a transaction, we reduce that # to a single hit. # But we go even further by staging our changes, and then bulk updating in one go. with transaction.atomic(): dirty_accounts = [] def recursive_update(account: Account): account.full_code = account.computed_full_code dirty_accounts.append(account) for child_account in account.get_children(): recursive_update(child_account) recursive_update(cached_account_tree) Account.objects.bulk_update(dirty_accounts, ['full_code'])
def generate_content(self, number): last_record = (self.items_per_page * int(number)) - 1 first_record = (last_record - self.items_per_page) + 1 root_comments = get_cached_trees( self.records)[first_record:last_record + 1] return [ tree.get_descendants(include_self=True) for tree in root_comments ]
def _apply_prefetch_to_instance(self, instance): if not hasattr(instance, '_cached_children'): descendants = instance.get_descendants(include_self=True) descendants = descendants.select_related('data_object') descendants = descendants.select_related( 'data_object__file_resource') instance = get_cached_trees(descendants)[0] return instance
def render(self, context): queryset = self.queryset_var.resolve(context) roots = get_cached_trees(queryset) roots.sort(key=lambda node: node.submit_date, reverse=True) bits = [ super(DateOrderedRecurseTreeNode, self)._render_node(context, node) for node in roots ] return ''.join(bits)
def get_table_of_contents(book_id, indent): tree_set = get_cached_trees( Page.objects.select_related('book').filter(book__pk=book_id).order_by( 'tree_id', 'lft')) tree_list = PageNode(tree_set, indent).get_list() return { 'tree_set': tree_set, 'tree_list': tree_list, }
def render(self, context): queryset = self.queryset_var.resolve(context) queryset = queryset.annotate(promotions_count=Count('promotions')) roots = get_cached_trees(queryset) roots.sort(key=lambda node: node.promotions_count, reverse=True) bits = [ super(PromotionOrderedRecurseTreeNode, self)._render_node(context, node) for node in roots ] return ''.join(bits)
def cache_tree_children(queryset): """ Alias to `mptt.utils.get_cached_trees`, suppressing errors for filtered querysets to avoid 500 errors being thrown when using the django admin search, and preserving previous behaviour as much as possible. """ allow_filtered = False if hasattr(queryset, 'query') and hasattr(queryset.query, 'has_filters'): allow_filtered = queryset.query.has_filters() return get_cached_trees(queryset, allow_filtered=allow_filtered)
def get_dmatree(request): organs = Organization.objects.all() top_nodes = get_cached_trees(organs) dicts = [] for n in top_nodes: dicts.append(recursive_node_to_dict(n, '')) # print json.dumps(dicts, indent=4) return JsonResponse({'trees': dicts})
def get_search_res(self): qs = self.model.objects.all() if self.request.GET.get('title'): qs = qs.filter(title__icontains=self.request.GET.get('title')) if self.request.GET.get('module'): qs = qs.filter(module_id=self.request.GET.get('module')) if self.request.GET.get('url'): qs = qs.filter(url__icontains=self.request.GET.get('url')) if qs.exists(): qs = qs.get_ancestors(include_self=True) home = get_cached_trees(qs)[0] return [home.serializable_object_with_children] else: return []
def get_adjacent_pages(book_id, page_id): tree_set = get_cached_trees( Page.objects.select_related('book').filter(book__pk=book_id).order_by( 'tree_id', 'lft')) tree_list = PageNode(tree_set, 0).get_list() i = 0 for i, p in enumerate(tree_list): if p.id == page_id: break return { 'previous_page': tree_list[i - 1] if i > 0 else None, 'next_page': tree_list[i + 1] if i + 1 < len(tree_list) else None, }
def gettree(request): print(request.GET) page_name = request.GET.get('page_name') or '' print(page_name) organs = Organization.objects.all() top_nodes = get_cached_trees(organs) dicts = [] for n in top_nodes: dicts.append(recursive_node_to_dict(n, page_name)) # print json.dumps(dicts, indent=4) return JsonResponse({'trees': dicts})
def get_adjacent_pages(book_id, page_id): tree_set = get_cached_trees(Page.objects .select_related('book') .filter(book__pk=book_id, status=Page.STATUS_CHOICES.public)) tree_list = PageListItem(tree_set, 0).get_list() i = 0 for i, p in enumerate(tree_list): if p.id == page_id: break return { 'previous_page': tree_list[i - 1] if i > 0 else None, 'next_page': tree_list[i + 1] if i + 1 < len(tree_list) else None, }
def get_blog_category_roots(blog_slug): cache_key = 'blog.templatetags.blog_tags.get_blog_category_roots({})'.format( blog_slug) cache_time = settings.CACHES['default']['TIMEOUT'] roots = cache.get(cache_key) if not roots: try: roots = get_cached_trees( Category.objects.filter(blog__slug=blog_slug).order_by( 'tree_id', 'lft')) cache.set(cache_key, roots, cache_time) except Category.DoesNotExist: roots = None return roots
def list(self, request, format=None): def course(node): return { 'name': node.name, 'id': node.id, 'slug': node.slug, } def category(node): return { 'name': node.name, 'id': node.id, 'children': list(map(category, node.get_children())), 'courses': list(map(course, node.course_set.all())), } categories = list(map(category, get_cached_trees(Category.objects.prefetch_related('course_set').all()))) return Response(categories)
def course_tree(request): def course(node): return { 'name': node.name, 'id': node.id, 'slug': node.slug, } def category(node): return { 'name': node.name, 'id': node.id, 'children': list(map(category, node.get_children())), 'courses': list(map(course, node.course_set.all())), } categories = list(map(category, get_cached_trees(Category.objects.prefetch_related('course_set').all()))) return HttpResponse(json.dumps(categories), content_type="application/json")
def render(self, context): category_slug = self.category_slug.resolve(context) cache_key = 'book.templatetags.book_tags.article_categories({})'.format(category_slug) cache_time = settings.CACHE_TIME_LONG tree_query_set = cache.get(cache_key) if not tree_query_set: try: tree_query_set = ArticleCategory.objects.filter(slug=category_slug).get_descendants(include_self=False) cache.set(cache_key, tree_query_set, cache_time) except ArticleCategory.DoesNotExist: tree_query_set = None roots = get_cached_trees(tree_query_set) nodes = [self._render_category(context, category) for category in roots] return ''.join(nodes)
def get_organization_tree(): """获取组织架构树状数据""" root_node = get_cached_trees(OrganizationMptt.objects.all())[0] tree_list = [] tree_dict = dict() tree_dict['dataId'] = root_node.id if root_node.user: tree_dict['text'] = root_node.name + ' ' + root_node.user.first_name else: tree_dict['text'] = root_node.name tree_dict['nodes'] = sorted(get_child_node_list(root_node), key=lambda x: x['text']) leader_username = root_node.get_leader_username() if leader_username: tag = '负责人:' + leader_username tree_dict['tags'] = [tag] else: tree_dict['tags'] = [str(root_node.get_title())] tree_list.append(tree_dict) return tree_list
def get_context_data(self, **kwargs): context = super().get_context_data() # we need to know the root nodes for each node which has no children nodes = context["page_obj"].object_list selectable_nodes = [node for node in nodes if node.level == 2] all_nominals = Nominal.objects.all().prefetch_related("children") # whole set # hits the DB but will cache result # root nodes are the groups for the select menu root_nominals = get_cached_trees(all_nominals) root_nominals.sort(key=lambda n: n.pk) options = [ { "group": node.get_root(), "option": node, "group_order": root_nominals.index(node.get_root()) } for node in selectable_nodes ] context["options"] = options return context
def get_category_roots(store_code, pg=False): cache_key = 'shop.templatetags.shop_tags.get_category_roots({},{})'.format( store_code, pg) cache_time = settings.CACHES['default']['TIMEOUT'] roots = cache.get(cache_key) if not roots: try: categories = Category.objects.filter( store__code=store_code).order_by('tree_id', 'lft') if pg: categories = categories.filter(pg=pg) roots = get_cached_trees(categories) cache.set(cache_key, roots, cache_time) except Category.DoesNotExist: roots = None return roots
def serialize_location_hierarchy(country, aliases_from_org=None): """ Serializes a country as a location hierarchy, e.g. { "name": "Rwanda", "children": [ { "name": "Kigali City", "aliases": ["Kigali", "Kigari"], "children": [ ... ] } ] } """ queryset = country.get_descendants(include_self=True) if aliases_from_org: from temba.locations.models import BoundaryAlias queryset = queryset.prefetch_related( Prefetch( "aliases", queryset=BoundaryAlias.objects.filter(org=aliases_from_org))) def _serialize_node(node): rendered = {"name": node.name} if aliases_from_org: rendered["aliases"] = [a.name for a in node.aliases.all()] children = node.get_children() if children: rendered["children"] = [] for child in node.get_children(): rendered["children"].append(_serialize_node(child)) return rendered return [_serialize_node(node) for node in get_cached_trees(queryset)][0]
def list(self, request, format=None): def course(node: Course): return { "name": node.name, "id": node.id, "slug": node.slug, } def category(node: Category): return { "name": node.name, "id": node.id, "children": list(map(category, node.get_children())), "courses": list(map(course, node.course_set.all())), } categories = list( map( category, get_cached_trees( Category.objects.prefetch_related("course_set").all()), )) return Response(categories)
def serialize_location_hierarchy(org): """ Serializes a country as a location hierarchy, e.g. { "name": "Rwanda", "children": [ { "name": "Kigali City", "aliases": ["Kigali", "Kigari"], "children": [ ... ] } ] } """ from temba.locations.models import BoundaryAlias queryset = org.country.get_descendants(include_self=True).prefetch_related( Prefetch("aliases", queryset=BoundaryAlias.objects.filter(org=org)) ) def _serialize_node(node): rendered = {"name": node.name} aliases = [a.name for a in node.aliases.all()] if aliases: rendered["aliases"] = aliases children = node.get_children() if children: rendered["children"] = [] for child in node.get_children(): rendered["children"].append(_serialize_node(child)) return rendered return [_serialize_node(node) for node in get_cached_trees(queryset)][0]
def get_context_data(self, **kwargs): context = {} context["columns"] = columns = [col for col in self.columns] mod_settings = ModuleSettings.objects.select_related('nominals_period').select_related('nominals_period__fy').first() current_period = mod_settings.nominals_period current_fy = current_period.fy first_period = current_fy.first_period() from_period = first_period to_period = last_period = current_period form_kwargs = { "initial": { "from_period": first_period, "to_period": last_period } } if self.request.GET: form_kwargs.update({ "data": self.request.GET }) context["form"] = form = TrialBalanceForm(**form_kwargs) if self.request.GET: if form.is_valid(): from_period = form.cleaned_data.get("from_period") to_period = form.cleaned_data.get("to_period") else: self.object_list = context["report"] = [] # show empty table return context nominals = Nominal.objects.all().prefetch_related("children") # hits the DB but will cache result root_nominals = get_cached_trees(nominals) # this means we can use get_ancestors() on the nodes now without hitting the DB again nominal_map = {nominal.pk: nominal for nominal in nominals} nominal_totals_for_period_range = ( NominalTransaction.objects .values("nominal") .annotate(total=Sum("value")) .filter(period__gte=from_period) .filter(period__lte=to_period) ) # get the start of the financial year the to_period is in from_period = first_period nominal_ytd_totals = ( NominalTransaction.objects .values("nominal") .annotate(total=Sum("value")) .filter(period__gte=from_period) .filter(period__lte=to_period) ) report = [] debit_total = 0 credit_total = 0 ytd_debit_total = 0 ytd_credit_total = 0 for nominal_total in nominal_totals_for_period_range: nominal_pk = nominal_total["nominal"] total = nominal_total["total"] if total > 0: debit_total += total else: credit_total += total parents = [ parent.name for parent in nominal_map[nominal_pk].get_ancestors()] for ytd in nominal_ytd_totals: if ytd["nominal"] == nominal_pk: ytd = ytd["total"] if ytd > 0: ytd_debit_total += ytd else: ytd_credit_total += ytd break nominal_report = { "nominal": nominal_map[nominal_pk].name, "total": total, "parents": parents, "ytd": ytd } report.append(nominal_report) context["debit_total"] = debit_total context["credit_total"] = credit_total context["ytd_debit_total"] = ytd_debit_total context["ytd_credit_total"] = ytd_credit_total self.object_list = context["report"] = report return context
def _get_top_nodes(self): if not hasattr(self, '_top_nodes'): self._top_nodes = get_cached_trees(Forum.objects.all()) return self._top_nodes
def handle_get_folders(self, data): root_folders = get_cached_trees(Folder._tree_manager.all()) return JsonResponse( {"rootFolder": _filer_folder_to_json_dict(None, root_folders)})
def get_cached_trees(self): """ Alias to `mptt.utils.get_cached_trees`. """ return utils.get_cached_trees(self)
def cache_tree_children(queryset): """ Alias to `mptt.utils.get_cached_trees`. """ return get_cached_trees(queryset)
def handle_get_folders(self, data): root_folders = get_cached_trees(Folder._tree_manager.all()) return JsonResponse({"rootFolder": _filer_folder_to_json_dict(None, root_folders)})
def get_ancestor_path(category_id): return get_cached_trees( Category.objects.get(pk=category_id).get_ancestors(include_self=False))
def handle_get_folders(self, data): shop = get_shop(self.request) root_folders = get_cached_trees(Folder._tree_manager.filter(_get_folder_query_filter(shop))) return JsonResponse({"rootFolder": _filer_folder_to_json_dict(None, root_folders)})