Get template name in template tag ( Django )

Looking at the source, while the Template object would have access to the template name (via .name) this value is never passed on to the Parser object and therefore not available to template tags.

There are various ways of making the template name available to the template itself (by adding it to the context) but not within the template tags.

As Daniel Roseman mentioned in the comments, if you can elaborate on what you're actually trying to achieve, there may be a better way to achieve what you want. No offence, but this sounds like it may be an XY problem.


Out of academic interest, I had a quick fiddle to see if it was possible. As far as I can see, it is possible but not without changing or monkey patching the django source.

Note: the following is not a recommended solution and merely hints at what may be required to actually make this work. Not to be used for production code.

By modifying django.template.base.py with the following changes, we add the .template_name attribute to the parser object making it available to template tags.

  1. Added optional arg to compile_string
  2. Added template name as extra attribute to parser
  3. Passed in the template name when calling compile_string()

To test this out, I defined the following tag which simply returns the template name in caps:

from django.template.base import Node, Library
register = Library()

class TemplateNameNode(Node):
    def __init__(self, template_name):
        self.name = template_name

    def render(self, context):
        return self.name.upper()

@register.tag
def caps_template_name(parser, token):
     return TemplateNameNode(parser.template_name)

and the following template:

{% load mytags %}
Template name in caps: {% caps_template_name %}

This seems to work when tested in ./manage.py shell:

>>> from django.template import loader, Context
>>> t = loader.get_template("test.html")
>>> t.render(Context({}))
u'\nTemplate name in caps: TEST.HTML\n'

While this seems to work, I should reiterate that manually patching the django source never a good solution and is subject to all sorts of misery when migrating to different versions.


You could perhaps do this with a context processor, but I'm not sure if these have access to the name of the template.

What will work is to make a wrapper for the rendering calls you do. Say you currently do the following:

from django.shortcuts import render
def index(request):
    return render(request, 'app/index.html', { 'foo': 'bar', })

If you create your own wrapper for this, you could add the template name to the dictionary before the actual render takes place:

from django.shortcuts import render
def myrender(request, template, dictionary):
    dictionary.update({'template_name': template})
    return render(request, template, dictionary)

Then in your views, change it as follows (assuming you saved the above function in myutils.py, and it is available on your path):

#from django.shortcuts import render <- delete this line
from myutils import myrender as render
def index(request):
    return render(request, 'app/index.html', { 'foo': 'bar', })

Now all your render calls will update the dictionary with the template name. In any template, then just use {{ template_name }} to get the name. You can of course also update other rendering function like render_to_response and such in a similar fashion.

Also, the import myrender as render might or might not confuse you later on because it is named like the Django function... if so, just import it without the "as render", and replace all render calls with myrender. Personally I'd prefer this since this makes it a drop-in replacement for the existing rendering functions.