views:

160

answers:

1

Has anyone written a block template tag that joins arbitrary html snippets with some separator, where empty items are omitted?

Could be useful for rendering menu-like lists, where displayed items are determined at run time and items to be joined require elaborate markup.

Thanks.

E.g.:

{% joinitems using ' | ' %}

  {% if show_a %}
  <p>Some HTML here</p>
  {% endif %}    

{% separator %}

  {% if show_b %}
  <p>And some here</p>
  {% endif %}

{% endjoinitems %}
+1  A: 

No answer in a whole hour... unacceptable. So I put this together myself.

class ItemSeparatorNode(template.Node):
    def __init__(self,separator):
        sep = separator.strip()
        if sep[0] == sep[-1] and sep[0] in ('\'','"'):
            sep = sep[1:-1]
        else:
            raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
        self.content = sep
    def render(self,context):
        return self.content

class JoinItemListNode(template.Node):
    def __init__(self,separator=ItemSeparatorNode("''"), items=()):
        self.separator = separator
        self.items = items
    def render(self,context):
        out = []
        empty_re = re.compile(r'^\s*$')
        for item in self.items:
            bit = item.render(context)
            if not empty_re.search(bit):
                out.append(bit)
        return self.separator.render(context).join(out)

@register.tag(name="joinitems")
def joinitems(parser,token):
    try:
        tagname,junk,sep_token = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters")
    if junk == 'using':
        sep_node = ItemSeparatorNode(sep_token)
    else:
        raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters")
    nodelist = []
    while True:
        nodelist.append(parser.parse(('separator','endjoinitems')))
        next = parser.next_token()
        if next.contents == 'endjoinitems':
            break

    return JoinItemListNode(separator=sep_node,items=nodelist)
Evgeny
heh heh - i do this all the time ... ask the question then second guess myself and go and find the answer on my own when my impatience grows.
thornomad