Josh Smeaton
Josh Smeaton

Reputation: 48730

How can I get the rendered output of a template within a template tag in django?

Disclaimer: This is a follow on question from my previous question.

I'm attempting to write a template tag in Django, that will render itself within the body of a Mako Template. I'm not sure that this is achievable, but it's something that'd be extremely useful to my project, and probably a lot of other people using Mako Templates within Django.

Here is the definition of my tag:

def extends_mako(parser, token):
    # wishlist below, this code does not work but it's what I want to achieve
    template_html = ''
    while (node = parser.nodelist.pop()):
        template_html += node.render()

Is the parser object capable of rendering the entire tree up to this point? My only idea at the moment, is to use the parser object to render (and remove from the tree) every node preceding this one. I'd then pass the output to Mako to render as HTML, and use that as the output to the render function of the Node I'm defining. My hope, is that when render is called on the template, it will only need to render this one node, since my template tag has already done the compilation on everything else. The intention is to have the extends_mako tag as the final tag in the tree.

I've done some quick pdb.set_trace investigation, but I can't see anything that helps thus far.

So; Is it possible to use the parser object, passed to the template tag, to compile the template, and retrieve the final rendered output?

Upvotes: 2

Views: 901

Answers (1)

Brandon Taylor
Brandon Taylor

Reputation: 34583

This isn't a solution specific to your problem, but might get you in the right direction. I recently took Django's "spaceless" template tag and added support to not strip the whitespace out when debugging.

Part of that template tag passes the list of template nodes collected between the {% spaceless %}{% endspaceless %} tags, which in theory, might get you the nodes preceeding your node...

from django.conf import settings
from django import template
from django.utils.html import strip_spaces_between_tags

register = template.Library()

class SmartSpacelessNode(template.Node):
    def __init__(self, nodelist):
        self.nodelist = nodelist

    def render(self, context):
        content = self.nodelist.render(context)
        #from here, you can probably delete the nodes after you've rendered
        #the content to a variable, then render your tag
        return content if settings.DEBUG else strip_spaces_between_tags(content.strip())

@register.tag
def smart_spaceless(parser, token):
    nodelist = parser.parse(('end_smart_spaceless',))
    parser.delete_first_token()
    return SmartSpacelessNode(nodelist)

Hope that helps you out.

Upvotes: 1

Related Questions