Ticket #2778: includeblock.patch

File includeblock.patch, 5.6 KB (added by SmileyChris, 8 years ago)

patch including tests and documentation

  • django/template/loader_tags.py

     
    1 from django.template import TemplateSyntaxError, TemplateDoesNotExist, resolve_variable
     1from django.template import TemplateSyntaxError, TemplateDoesNotExist, VariableDoesNotExist, resolve_variable
    22from django.template import Library, Node
    33from django.template.loader import get_template, get_template_from_string, find_template_source
    44from django.conf import settings
     
    113113        except:
    114114            return '' # Fail silently for invalid included templates.
    115115
     116class IncludeBlockNode(Node):
     117    def __init__(self, template_name, block_name, template_dirs=None):
     118        self.template_name = template_name
     119        self.block_name = block_name
     120        self.template_dirs = template_dirs
     121
     122    def render(self, context):
     123        try:
     124            template_name = resolve_variable(self.template_name, context)
     125            block_name = resolve_variable(self.block_name, context)
     126        except VariableDoesNotExist:
     127            # Fail silently if either variable can not be resolved.
     128            return ''
     129        try:
     130            template = get_template(template_name)
     131        except TemplateSyntaxError, e:
     132            if settings.TEMPLATE_DEBUG:
     133                raise
     134            return ''
     135        except:
     136            return '' # Fail silently for invalid included template.
     137        for block_node in template.nodelist.get_nodes_by_type(BlockNode):
     138            if block_name == block_node.name:
     139                # Block matches, render it.
     140                return block_node.render(context)
     141        # No matching block was found.
     142        return ''
     143
    116144def do_block(parser, token):
    117145    """
    118146    Define a block that can be overridden by child templates.
     
    172200        return ConstantIncludeNode(path[1:-1])
    173201    return IncludeNode(bits[1])
    174202
     203def do_includeblock(parser, token):
     204    """
     205    Loads a block from another template and renders it with the current
     206    context. The first argument is the template name, the second is the block.
     207    Both can be variables rendered from the context or given as constants by
     208    surrounding with quotes.
     209   
     210    Example::
     211   
     212        {% includeblock "foo/some_include.htm" "bar_block" %}
     213    """
     214    bits = token.split_contents()
     215    if len(bits) != 3:
     216        raise TemplateSyntaxError, "%r tag takes two arguments: the name of the template and the block to be included" % bits[0]
     217    return IncludeBlockNode(*bits[1:])
     218
    175219register.tag('block', do_block)
    176220register.tag('extends', do_extends)
    177221register.tag('include', do_include)
     222register.tag('includeblock', do_includeblock)
  • docs/templates.txt

     
    577577
    578578See also: ``{% ssi %}``.
    579579
     580includeblock
     581~~~~~~~~~~~~
     582
     583Similar to ``include`` but rather than rendering the entire template, this
     584renders a specific ``block`` of the given template with the current context.
     585
     586Both the template name and the block name can either be variables or
     587hard-coded (quoted) strings.
     588
     589This example includes the "navigation" block of the template "main.htm"::
     590
     591        {% includeblock "main.htm" "navigation" %}
     592
    580593load
    581594~~~~
    582595
  • tests/regressiontests/templates/tests.py

     
    418418            # Inheritance from local context with variable parent template
    419419            'inheritance25': ("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'),
    420420
     421            ### INCLUDEBLOCK TAG ######################################################
     422           
     423            # Loading a block tag
     424            'includeblock01': ('1{% includeblock "inheritance02" "first" %}3', {}, '123'),
     425           
     426            # Loading a block tag using the template name as a context variable
     427            'includeblock02': ('3{% includeblock template_name "second" %}5', {'template_name': 'inheritance02'}, '345'),
     428
     429            # Loading a block tag using the block name as a context variable
     430            'includeblock03': ('3{% includeblock "inheritance02" block_name %}5', {'block_name': 'second'}, '345'),
     431
     432            # Loading a block tag using context variables
     433            'includeblock04': ('3{% includeblock template_name block_name %}5', {'template_name': 'inheritance02', 'block_name': 'second'}, '345'),
     434
     435            # Invalid template
     436            'includeblock05': ('a{% includeblock "not a real template" "blockname" %}b', {}, 'ab'),
     437           
     438            # Invalid block
     439            'includeblock06': ('b{% includeblock "inheritance02" "invalidblockname" %}c', {}, 'bc'),
     440           
     441            # Invalid template context variable
     442            'includeblock07': ('a{% includeblock invalidtemplatename "blockname" %}b', {}, 'ab'),
     443           
     444            # Invalid block context variable
     445            'includeblock08': ('b{% includeblock "inheritance02" invalidblockname %}c', {}, 'bc'),
     446           
    421447            ### I18N ##################################################################
    422448
    423449            # {% spaceless %} tag
Back to Top