I’m trying to create a custom template tag that only renders a block of code once, regardless of how many times the tag/partial that contains it is executed.
This is how I’ve implemented it, but as you can see, it’s a bit hackish:
my_partial.html:
{% once mycontent %}
this will only show once
{% endonce%}
my_template.html:
{% load my_tags %}
{% for i in list %}
{% my_partial %}
{% endfor %}
my_tags.py:
@register.inclusion_tag('my_partial.html',takes_context=True)
def my_partial(context):
return dict(arbitrary extra data)
@register.tag(name="once")
def do_once(parser, token):
try:
# Splitting by None == splitting by spaces.
tag_name, var_name = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
nodelist = parser.parse(('endonce',))
parser.delete_first_token()
return DoOnceNode(nodelist, var_name)
class DoOnceNode(template.Node):
def __init__(self, nodelist, var_name):
self.nodelist = nodelist
self.var_name = '_do_once_'+var_name
def render(self, context):
request = context['request']
# Make request.GET mutable.
request.GET = dict(request.GET)
if self.var_name in request.GET:
return ''
else:
request.GET[self.var_name] = 1
return self.nodelist.render(context)
Specifically, I’m using the request.GET dictionary as a mutable global scope. It’s hackish and obviously not what the request object is designed to do, but it works.
Ideally, I’d like to use something like the context, but I found that it isn’t shared between calls to this tag. i.e. self.var_name in context is always False, rendering it useless as a global scope.
Why isn’t context shared the same way request is shared? Is there someway to make it truly shared, or is there some other object I can use to store globally accessible variables within a request?
I’m not exactly sure what you need to accomplish or if your approach is indeed the best approach, but I’d suggest your look into the
forloop.firstvariable before you go too far down this road. Your approach seems awkward at best at a glance, but I could be wrong since I don’t know the specifics of the situationdjango for template tag
Most likely you should be able to make this work to your needs, however if it falls short I’d suggest that the source for the
fortemplate tag (and it’sforloopvariable) would likely be very illustrative on how you might implement what you’re looking to do.