- Author:
- daniellindsley
- Posted:
- November 5, 2008
- Language:
- Python
- Version:
- 1.0
- Score:
- 2 (after 2 ratings)
Works exactly like the standard "extends" tag but enables one to fallback on a default template. This tag is LIMITED, as it falls back to the next template with the same name that DOES NOT contain "extends_default" (does NOT simulate full inheritance, just a single level).
A partial solution to problems like http://jeffcroft.com/blog/2008/aug/05/default-templates-django/.
MIT licensed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | from django.template import TemplateSyntaxError, TemplateDoesNotExist
from django.template import Library, Node, TextNode
from django.template.loader_tags import ExtendsNode
from django.template.loader import get_template_from_string, make_origin
from django.template.loaders.filesystem import get_template_sources
from django.conf import settings
register = Library()
def find_default_template_source(name, dirs=None):
try:
source, display_name = load_default_template_source(name, dirs)
return (source, make_origin(display_name, load_default_template_source, name, dirs))
except TemplateDoesNotExist:
raise TemplateDoesNotExist, name
class SawExtendsSelf(IOError): pass
def load_default_template_source(template_name, template_dirs=None):
tried = []
for filepath in get_template_sources(template_name, template_dirs):
try:
template = open(filepath)
file_source_line_1 = template.readline()
if 'load extends_default' in file_source_line_1:
file_source_line_2 = template.readline()
if 'extends_default' in file_source_line_2:
raise SawExtendsSelf
template.close()
return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
except SawExtendsSelf:
tried.append("%s (Saw extends_default and continuing...)" % filepath)
except IOError:
tried.append(filepath)
if tried:
error_msg = "Tried %s" % tried
else:
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
raise TemplateDoesNotExist, error_msg
class ExtendsDefaultNode(ExtendsNode):
must_be_first = False
def __repr__(self):
if self.parent_name_expr:
return "<ExtendsDefaultNode: extends %s>" % self.parent_name_expr.token
return '<ExtendsDefaultNode: extends "%s">' % self.parent_name
def get_parent(self, context):
if self.parent_name_expr:
self.parent_name = self.parent_name_expr.resolve(context)
parent = self.parent_name
if not parent:
error_msg = "Invalid template name in 'extends_default' tag: %r." % parent
if self.parent_name_expr:
error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token
raise TemplateSyntaxError, error_msg
if hasattr(parent, 'render'):
return parent # parent is a Template object
try:
source, origin = find_default_template_source(parent, self.template_dirs)
except TemplateDoesNotExist:
raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent
else:
return get_template_from_string(source, origin, parent)
def do_extends_default(parser, token):
"""
Enables extension of a default template with the same name.
Usage:
{% load extends_default %}
{% extends_default "same_directory/hierarchy/template_name.html" %}
Works exactly like the standard "extends" tag but enables one to fallback
on a default template. This tag is LIMITED, as it falls back to the next
template with the same name that DOES NOT contain "extends_default" (does
NOT simulate full inheritance, just a single level).
"""
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError, "'%s' takes one argument" % bits[0]
parent_name, parent_name_expr = None, None
if bits[1][0] in ('"', "'") and bits[1][-1] == bits[1][0]:
parent_name = bits[1][1:-1]
else:
parent_name_expr = parser.compile_filter(bits[1])
nodelist = parser.parse()
if nodelist.get_nodes_by_type(ExtendsDefaultNode) or nodelist.get_nodes_by_type(ExtendsNode):
raise TemplateSyntaxError, "'%s' cannot appear more than once in the same template" % bits[0]
return ExtendsDefaultNode(nodelist, parent_name, parent_name_expr)
register.tag('extends_default', do_extends_default)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.