/sitetree/templatetags/sitetree.py

https://github.com/bluemarble/django-sitetree · Python · 258 lines · 226 code · 18 blank · 14 comment · 13 complexity · 1b814bf024a55ff877c811b8d9319804 MD5 · raw file

  1. from django.conf import settings
  2. from django import template
  3. from django import VERSION
  4. from django.templatetags.static import PrefixNode
  5. from ..sitetreeapp import SiteTree
  6. register = template.Library()
  7. # All utility methods are implemented in SiteTree class
  8. sitetree = SiteTree()
  9. DJANGO_VERSION_INT = int('%s%s%s' % VERSION[:3])
  10. @register.tag
  11. def sitetree_tree(parser, token):
  12. """Parses sitetree tag parameters.
  13. Two notation types are possible:
  14. 1. Two arguments:
  15. {% sitetree_tree from "mytree" %}
  16. Used to render tree for "mytree" site tree.
  17. 2. Four arguments:
  18. {% sitetree_tree from "mytree" template "sitetree/mytree.html" %}
  19. Used to render tree for "mytree" site tree using specific
  20. template "sitetree/mytree.html"
  21. """
  22. tokens = token.split_contents()
  23. use_template = detect_clause('template', tokens)
  24. tokensNum = len(tokens)
  25. if tokensNum in (3, 5):
  26. tree_alias = tokens[2][1:-1]
  27. return sitetree_treeNode(tree_alias, use_template)
  28. else:
  29. raise template.TemplateSyntaxError, "%r tag requires two arguments. E.g. {%% sitetree_tree from \"mytree\" %%}." % tokens[0]
  30. @register.tag
  31. def sitetree_children(parser, token):
  32. """Parses sitetree_children tag parameters.
  33. Six arguments:
  34. {% sitetree_children of someitem for menu template "sitetree/mychildren.html" %}
  35. Used to render child items of specific site tree 'someitem'
  36. using template "sitetree/mychildren.html" for menu navigation.
  37. Basically template argument should contain path to current template itself.
  38. Allowed navigation types: 1) menu; 2) sitetree.
  39. """
  40. tokens = token.split_contents()
  41. use_template = detect_clause('template', tokens)
  42. tokensNum = len(tokens)
  43. if tokensNum == 5 and tokens[1] == 'of' and tokens[3] == 'for' and tokens[4] in ('menu', 'sitetree') and use_template is not None:
  44. tree_item = tokens[2]
  45. navigation_type = tokens[4]
  46. return sitetree_childrenNode(tree_item, navigation_type, use_template)
  47. else:
  48. raise template.TemplateSyntaxError, "%r tag requires six arguments. E.g. {%% sitetree_children of someitem for menu template \"sitetree/mychildren.html\" %%}." % tokens[0]
  49. @register.tag
  50. def sitetree_breadcrumbs(parser, token):
  51. """Parses sitetree_breadcrumbs tag parameters.
  52. Two notation types are possible:
  53. 1. Two arguments:
  54. {% sitetree_breadcrumbs from "mytree" %}
  55. Used to render breadcrumb path for "mytree" site tree.
  56. 2. Four arguments:
  57. {% sitetree_breadcrumbs from "mytree" template "sitetree/mycrumb.html" %}
  58. Used to render breadcrumb path for "mytree" site tree using specific
  59. template "sitetree/mycrumb.html"
  60. """
  61. tokens = token.split_contents()
  62. use_template = detect_clause('template', tokens)
  63. tokensNum = len(tokens)
  64. if tokensNum == 3:
  65. tree_alias = tokens[2][1:-1]
  66. return sitetree_breadcrumbsNode(tree_alias, use_template)
  67. else:
  68. raise template.TemplateSyntaxError, "%r tag requires two arguments. E.g. {%% sitetree_breadcrumbs from \"mytree\" %%}." % tokens[0]
  69. @register.tag
  70. def sitetree_menu(parser, token):
  71. """Parses sitetree_menu tag parameters.
  72. {% sitetree_menu from "mytree" include "trunk,1,level3" %}
  73. Used to render trunk, branch with id 1 and branch aliased 'level3'
  74. elements from "mytree" site tree as a menu.
  75. These are reserved aliases:
  76. * 'trunk' - items without parents
  77. * 'this-children' - items under item resolved as current for the current page
  78. * 'this-siblings' - items under parent of item resolved as current for
  79. the current page (current item included)
  80. * 'this-ancestor-children' - items under grandparent item (closest to root)
  81. for the item resolved as current for the current page
  82. {% sitetree_menu from "mytree" include "trunk,1,level3" template "sitetree/mymenu.html" %}
  83. """
  84. tokens = token.split_contents()
  85. use_template = detect_clause('template', tokens)
  86. tokensNum = len(tokens)
  87. if tokensNum == 5 and tokens[3] == 'include':
  88. tree_alias = tokens[2][1:-1]
  89. tree_branches = tokens[4][1:-1]
  90. return sitetree_menuNode(tree_alias, tree_branches, use_template)
  91. else:
  92. raise template.TemplateSyntaxError, "%r tag requires four arguments. E.g. {%% sitetree_menu from \"mytree\" include \"trunk,1,level3\" %%}." % tokens[0]
  93. @register.tag
  94. def sitetree_url(parser, token):
  95. """This tag is much the same as Django built-in 'url' tag.
  96. The difference is that after 'for' it should get TreeItem object.
  97. And, yes, you can pass some arguments after that TreeItem object.
  98. """
  99. tokens = token.contents.split()
  100. tokensNum = len(tokens)
  101. if tokensNum >= 3 and tokens[1] == 'for':
  102. sitetree_item = tokens[2]
  103. tag_arguments = tokens[3:]
  104. return sitetree_urlNode(sitetree_item, tag_arguments)
  105. else:
  106. raise template.TemplateSyntaxError, "%r tag should look like {%% sitetree_url for someitem params %%}." % tokens[0]
  107. @register.tag
  108. def sitetree_page_title(parser, token):
  109. """Renders title for current page, resolved against sitetree item
  110. representing current URL.
  111. """
  112. tokens = token.split_contents()
  113. if len(tokens) == 3:
  114. tree_alias = tokens[2][1:-1]
  115. return sitetree_page_titleNode(tree_alias)
  116. else:
  117. raise template.TemplateSyntaxError, "%r tag requires two arguments. E.g. {%% sitetree_page_title from \"mytree\" %%}." % tokens[0]
  118. @register.simple_tag
  119. def sitetree_admin_img_url_prefix():
  120. """Returns static admin images URL prefix. """
  121. if DJANGO_VERSION_INT >= 140:
  122. return '%sadmin/img' % PrefixNode.handle_simple('STATIC_URL')
  123. return '%simg/admin' % PrefixNode.handle_simple('ADMIN_MEDIA_PREFIX')
  124. class sitetree_treeNode(template.Node):
  125. """Renders tree items from specified site tree."""
  126. def __init__(self, tree_alias, use_template):
  127. if use_template is None:
  128. use_template = 'sitetree/tree.html'
  129. self.template = template.loader.get_template(use_template)
  130. self.tree_alias = tree_alias
  131. def render(self, context):
  132. tree_items = sitetree.tree(self.tree_alias, context)
  133. my_context = template.Context({'sitetree_items': tree_items, 'user': context['user']})
  134. return self.template.render(my_context)
  135. class sitetree_childrenNode(template.Node):
  136. """Renders tree items under specified parent site tree item."""
  137. def __init__(self, tree_item, navigation_type, use_template):
  138. self.use_template = use_template
  139. self.tree_item = tree_item
  140. self.navigation_type = navigation_type
  141. def render(self, context):
  142. return sitetree.children(self.tree_item, self.navigation_type, self.use_template, context)
  143. class sitetree_breadcrumbsNode(template.Node):
  144. """Renders breadcrumb trail items from specified site tree."""
  145. def __init__(self, tree_alias, use_template):
  146. if use_template is None:
  147. use_template = 'sitetree/breadcrumbs.html'
  148. self.template = template.loader.get_template(use_template)
  149. self.tree_alias = tree_alias
  150. def render(self, context):
  151. tree_items = sitetree.breadcrumbs(self.tree_alias, context)
  152. my_context = template.Context({'sitetree_items': tree_items, 'user': context['user']})
  153. return self.template.render(my_context)
  154. class sitetree_menuNode(template.Node):
  155. """Renders specified site tree menu items."""
  156. def __init__(self, tree_alias, tree_branches, use_template):
  157. if use_template is None:
  158. use_template = 'sitetree/menu.html'
  159. self.template = template.loader.get_template(use_template)
  160. self.tree_alias = tree_alias
  161. self.tree_branches = tree_branches
  162. def render(self, context):
  163. tree_items = sitetree.menu(self.tree_alias, self.tree_branches, context)
  164. my_context = template.Context({'sitetree_items': tree_items, 'user': context['user'], 'request': context['request']})
  165. return self.template.render(my_context)
  166. class sitetree_urlNode(template.Node):
  167. """Resolves and renders specified url."""
  168. def __init__(self, sitetree_item, tag_arguments):
  169. self.sitetree_item = sitetree_item
  170. self.tag_arguments = tag_arguments
  171. def render(self, context):
  172. resolved_url = sitetree.url(self.sitetree_item, self.tag_arguments, context)
  173. return resolved_url
  174. class sitetree_page_titleNode(template.Node):
  175. """Renders page title from specified site tree."""
  176. def __init__(self, tree_alias):
  177. self.tree_alias = tree_alias
  178. def render(self, context):
  179. return sitetree.get_current_page_title(self.tree_alias, context)
  180. def detect_clause(clause_name, tokens):
  181. """Helper function detects a certain clause in tag tokens list.
  182. Returns its value.
  183. """
  184. if clause_name in tokens:
  185. tindex = tokens.index(clause_name)
  186. clause_value = tokens[tindex + 1][1:-1]
  187. del tokens[tindex:tindex + 2]
  188. else:
  189. clause_value = None
  190. return clause_value