/menus/utils.py

https://github.com/daonb/django-cms · Python · 201 lines · 169 code · 9 blank · 23 comment · 60 complexity · 0a457a7ebe2af9150aba40adaaafbf2d MD5 · raw file

  1. def mark_descendants(nodes):
  2. for node in nodes:
  3. node.descendant = True
  4. mark_descendants(node.childrens)
  5. def make_tree(request, items, levels, url, ancestors, descendants=False, current_level=0, to_levels=100, active_levels=0):
  6. from cms.models import Page
  7. """
  8. builds the tree of all the navigation extender nodes and marks them with some metadata
  9. """
  10. levels -= 1
  11. current_level += 1
  12. found = False
  13. for item in items:
  14. item.level = current_level
  15. if descendants and not found:
  16. item.descendant = True
  17. item.ancestors_ascending = ancestors
  18. if item.get_absolute_url() == url:
  19. item.selected = True
  20. item.descendant = False
  21. levels = active_levels
  22. descendants = True
  23. found = True
  24. last = None
  25. for anc in ancestors:
  26. if not isinstance(anc, Page) and last:
  27. last = None
  28. if hasattr(last, 'childrens'):
  29. for child in last.childrens:
  30. if isinstance(child, Page):
  31. child.sibling = True
  32. else:
  33. last = anc
  34. anc.ancestor = True
  35. if last:
  36. if hasattr(last, 'childrens'):
  37. for child in last.childrens:
  38. if isinstance(child, Page):
  39. child.sibling = True
  40. elif found:
  41. item.sibling = True
  42. if levels == 0 and not hasattr(item, "ancestor" ) or item.level == to_levels or not hasattr(item, "childrens"):
  43. item.childrens = []
  44. else:
  45. make_tree(request, item.childrens, levels, url, ancestors+[item], descendants, current_level, to_levels, active_levels)
  46. if found:
  47. for item in items:
  48. if not hasattr(item, "selected"):
  49. item.sibling = True
  50. def get_extended_navigation_nodes(request, levels, ancestors, current_level, to_levels, active_levels, mark_sibling, path):
  51. """
  52. discovers all navigation nodes from navigation extenders
  53. """
  54. func_name = path.split(".")[-1]
  55. ext = __import__(".".join(path.split(".")[:-1]),(),(),(func_name,))
  56. func = getattr(ext, func_name)
  57. items = func(request)
  58. descendants = False
  59. for anc in ancestors:
  60. if hasattr(anc, 'selected'):
  61. if anc.selected:
  62. descendants = True
  63. if len(ancestors) and hasattr(ancestors[-1], 'ancestor'):
  64. make_tree(request, items, 100, request.path, ancestors, descendants, current_level, 100, active_levels)
  65. make_tree(request, items, levels, request.path, ancestors, descendants, current_level, to_levels, active_levels)
  66. if mark_sibling:
  67. for item in items:
  68. if not hasattr(item, "selected" ):
  69. item.sibling = True
  70. return items
  71. def find_children(target, pages, levels=100, active_levels=0, ancestors=None, selected_pk=0, soft_roots=True, request=None, no_extended=False, to_levels=100):
  72. """
  73. recursive function for marking all children and handling the active and inactive trees with the level limits
  74. """
  75. if not hasattr(target, "childrens"):
  76. target.childrens = []
  77. if ancestors == None:
  78. ancestors = []
  79. if target.pk in ancestors:
  80. target.ancestor = True
  81. if target.pk == selected_pk:
  82. levels = active_levels
  83. if (levels <= 0 or (target.soft_root and soft_roots)) and not target.pk in ancestors:
  84. return
  85. mark_sibling = False
  86. for page in pages:
  87. if page.parent_id and page.parent_id == target.pk:
  88. if hasattr(target, "selected") or hasattr(target, "descendant"):
  89. page.descendant = True
  90. if len(target.childrens):
  91. target.childrens[-1].last = False
  92. page.ancestors_ascending = [target] + list(target.ancestors_ascending)
  93. page.home_pk_cache = target.home_pk_cache
  94. page.last = True
  95. target.childrens.append(page)
  96. find_children(page,
  97. pages,
  98. levels-1,
  99. active_levels,
  100. ancestors,
  101. selected_pk,
  102. soft_roots,
  103. request,
  104. no_extended,
  105. to_levels)
  106. if hasattr(page, "selected"):
  107. mark_sibling = True
  108. if target.navigation_extenders and (levels > 0 or target.pk in ancestors) and not no_extended and target.level < to_levels:
  109. target.childrens += get_extended_navigation_nodes(request,
  110. levels,
  111. list(target.ancestors_ascending) + [target],
  112. target.level,
  113. to_levels,
  114. active_levels,
  115. mark_sibling,
  116. target.navigation_extenders)
  117. def cut_levels(nodes, level):
  118. """
  119. For cutting the nav_extender levels if you have a from_level in the navigation.
  120. """
  121. result = []
  122. if nodes:
  123. if nodes[0].level == level:
  124. return nodes
  125. for node in nodes:
  126. result += cut_levels(node.childrens, level)
  127. return result
  128. def find_selected(nodes):
  129. """
  130. Finds a selected nav_extender node
  131. """
  132. for node in nodes:
  133. if hasattr(node, "selected"):
  134. return node
  135. if hasattr(node, "ancestor"):
  136. result = find_selected(node.childrens)
  137. if result:
  138. return result
  139. def set_language_changer(request, func):
  140. """
  141. Sets a language chooser function that accepts one parameter: language
  142. The function should return a url in the supplied language
  143. normally you would want to give it the get_absolute_url function with an optional language parameter
  144. example:
  145. def get_absolute_url(self, language=None):
  146. reverse('product_view', args=[self.get_slug(language=language)])
  147. Use this function in your nav extender views that have i18n slugs.
  148. """
  149. request._language_changer = func
  150. def language_changer_decorator(language_changer):
  151. """
  152. A decorator wrapper for set_language_changer.
  153. from menus.utils import language_changer_decorator
  154. @language_changer_decorator(function_get_language_changer_url)
  155. def my_view_function(request, somearg):
  156. pass
  157. """
  158. def _decorator(func):
  159. def _wrapped(request, *args, **kwargs):
  160. set_language_changer(request, language_changer)
  161. return func(request, *args, **kwargs)
  162. _wrapped.__name__ = func.__name__
  163. _wrapped.__doc__ = func.__doc__
  164. return _wrapped
  165. return _decorator
  166. def simple_language_changer(func):
  167. def _wrapped(request, *args, **kwargs):
  168. def _language_changer(lang):
  169. return request.path
  170. set_language_changer(request, _language_changer)
  171. return func(request, *args, **kwargs)
  172. _wrapped.__name__ = func.__name__
  173. _wrapped.__doc__ = func.__doc__
  174. return _wrapped
  175. from django.conf import settings
  176. def handle_navigation_manipulators(navigation_tree, request):
  177. for handler_function_name, name in settings.CMS_NAVIGATION_MODIFIERS:
  178. func_name = handler_function_name.split(".")[-1]
  179. modifier = __import__(".".join(handler_function_name.split(".")[:-1]),(),(),(func_name,))
  180. handler_func = getattr(modifier, func_name)
  181. handler_func(navigation_tree, request)
  182. return navigation_tree