I had an issue with the django templating system, where by if I included several different files at the same level on one template.. and all the included templates extended the same base template. It would render the defined blocks for the first inclusion for all. i.e. everything in the parent that is being extended would be not updated for the subsequent inclusion.
So, if anyone else has this problem. I have a solution that I sorta wanted for other reasons anyway. It's called a decorator tag, you can include and extend a template at the same time - in-line, with local context scoping so it only affects that tag.
This is also a nice way to avoid creating .html files for simple extending purposes.
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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | Inside main template:
{% block step_1 %}
<!-- Step 1: Item Details -->
{% with wizard.step_1 as step %}
{% decorate "item/wizard/ajax_step_decorator.html" %}
{% localblock step_ready_js %}
$(this).standardWizardStepFormBind(step, formId);
{% endlocalblock %}
{% enddecorate %}
{% endwith %}
<!-- / Step 1 -->
{% endblock %}
{% block step_2 %}
<!-- Step 2: Category Select -->
{% with wizard.step_2 as step %}
{% decorate "item/wizard/ajax_step_decorator.html" %}
{% localblock step_ready_js %}
$(this).categorySelectLiveQueryActions();
{% endlocalblock %}
{% enddecorate %}
{% endwith %}
<!-- / Step 2 -->
{% endblock %}
Decorator: item/wizard/ajax_step_decorator.html
{% load conversation %}
{% load common_webdesign %}
<form id="{{ step.get_form_id }}" name="{{ step.get_form_name }}" action="{{ step.get_action }}" method="POST" class="standard-form">{% cid_hidden %}
<div id="{{ step.get_div_id }}">
<div id="{{ step.get_inner_div_id }}">
{% if step.available %}
{% localblock step_available_body %}
{% include step.template_name %}
{% endlocalblock %}
{% else %}
{% localblock step_unavailable_body %}
{% include "item/wizard/disabled_step_block.html" %}
{% endlocalblock %}
{% endif %}
</div>
</div>
</form>
<script language="javascript">
$(this).ready(function() {
// Provides: step, formName, formId & disabledId
{% include "item/wizard/step_javascript_vars.html" %}
{% localblock step_ready_js %}{% endlocalblock %}
});
</script>
Implementation (templatetags):
def decorate(parser, token):
nodelist = parser.parse(('enddecorate',))
parser.delete_first_token()
try:
tag_name, template_name = token.split_contents()
except ValueError:
raise TemplateSyntaxError, "%r tag requires one argument" % \
token.contents.split()[0]
decorateNode = DecorateNode(nodelist, parser.compile_filter(template_name))
return decorateNode
class DecorateNode(Node):
def __init__(self, nodelist, template_name):
self.nodelist = nodelist
self.template_name = template_name
self.blocks = dict([(n.name, n) for n in nodelist.get_nodes_by_type(LocalBlockNode)])
def render(self, context):
template_name = self.template_name.resolve(context)
t = get_template(template_name)
context['localblock'] = self.blocks
return t.render(context)
class LocalBlockNode(Node):
def __init__(self, name, nodelist, parent=None):
self.name, self.nodelist, self.parent = name, nodelist, parent
def __repr__(self):
return "<LocalBlock Node: %s. Contents: %r>" % (self.name, self.nodelist)
def render(self, context):
try:
if self.name and 'localblock' in context:
local_blocks = context['localblock']
if local_blocks and self.name in local_blocks:
block = local_blocks[self.name]
return block.nodelist.render(context)
except Except, e:
logger.error("Failed to render LocalBlockNode")
logger.error(e)
raise
# Failed to render contextual element, render this one:
return self.nodelist.render(context)
def localblock(parser, token):
"""
Define a block that can be overridden by child templates.
"""
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError, "'%s' tag takes only one argument" % bits[0]
block_name = bits[1]
nodelist = parser.parse(('endlocalblock', 'endlocalblock %s' % block_name))
parser.delete_first_token()
return LocalBlockNode(block_name, nodelist)
register.tag(localblock)
register.tag(decorate)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
I think this is what I need... but i don't really understand what it does from your example... probably because it's hard to read with the javascript interspersed... something simple for simpletons please!
#
Please login first before commenting.