def do_include(parser, token): """ A copy of Django's built-in {% include ... %} tag that uses our custom IncludeNode to allow us to load dummy context for the pattern library. """ bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0]) options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'only': value = True else: raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value isolated_context = options.get('only', False) namemap = options.get('with', {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap, isolated_context=isolated_context)
def blockinclude(parser, token): bits = token.split_contents() if len(bits) < 2: raise template.TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0] ) options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise template.TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = template.base.token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise template.TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'only': value = True else: raise template.TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value isolated_context = options.get('only', False) namemap = options.get('with', {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) filter_compile = parser.compile_filter(bits[1]) nodelist = parser.parse(('endblockinclude',)) parser.delete_first_token() blocks_renaming = {} for nl in get_blocks(nodelist): if nl.name in parser.__loaded_blocks: parser.__loaded_blocks.remove(nl.name) idx = 1 name = nl.name + '_' + str(idx) while name in parser.__loaded_blocks: idx += 1 name = nl.name + '_' + str(idx) blocks_renaming[nl.name] = name nl.name = name parser.__loaded_blocks.append(nl.name) return BlockIncludeNode( nodelist, filter_compile, extra_context=namemap, isolated_context=isolated_context, blocks_renaming=blocks_renaming )
def do_extends(parser, token): """ Signal that this template extends a parent template. This tag may be used in two ways: ``{% extends "base" %}`` (with quotes) uses the literal value "base" as the name of the parent template to extend, or ``{% extends variable %}`` uses the value of ``variable`` as either the name of the parent template to extend (if it evaluates to a string) or as the parent template itself (if it evaluates to a Template object). """ bits = token.split_contents() print('bits" ++++++++>', type(bits[1])) print('do_extends: ', token) if len(bits) != 2: raise TemplateSyntaxError("'%s' takes one argument" % bits[0]) site = Site.objects.get_current() bits[1] = '"{0}/{1}"'.format(site.domain, bits[1].strip("'").strip('"')) print('parser.origin.template_name: ', parser.origin.template_name) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) parent_name = parser.compile_filter(bits[1]) print('parent_name: ----------------------->', type(parent_name), parent_name) nodelist = parser.parse() if nodelist.get_nodes_by_type(ExtendsNode): raise TemplateSyntaxError( "'%s' cannot appear more than once in the same template" % bits[0]) print(nodelist, parent_name) return ExtendsNode(nodelist, parent_name)
def do_component(parser, token): bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0]) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) parent_name = parser.compile_filter(bits[1]) nodelist = parser.parse(('endcomponent', )) # This check is kept for backwards-compatibility. See #3100. endblock = parser.next_token() acceptable_endblocks = ('endcomponent') if endblock.contents not in acceptable_endblocks: parser.invalid_block_tag(endblock, 'endcomponent', acceptable_endblocks) for node in nodelist: if isinstance(node, TextNode) and len( node.s.strip()) == 0 or isinstance(node, CommentNode): # whitespace/comments are a-ok continue # The ExtendsNode has to be the first non-text node. if not isinstance(node, SlotNode): raise TemplateSyntaxError("'%s' only allows slots" % bits[0]) options = {} isolated_context, namemap = parse_options(bits, options, parser) return ComponentNode(nodelist, parent_name, extra_context=namemap, isolated_context=isolated_context)
def do_embed(parser, token): """{% embed %} template tag. Allows to include a template and optionally override its slots, in a similar fashion to block tags in extended templates. Example:: {% embed 'section.html' %} {% slot title %}<h1>Title</h1>{% endslot %} {% slot content %}<p>Content</p>{% endslot %} {% endembed %} You may use the ``only`` argument and keyword arguments using ``with`` like when using ``{% include %}`` """ # Exact copy from do_include_node() bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0]) options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError("The %r option was specified more " "than once." % option) if option == "with": value = token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' "one keyword argument." % bits[0]) elif option == "only": value = True else: raise TemplateSyntaxError( f"Unknown argument for {bits[0]!r} tag: {option!r}.") options[option] = value isolated_context = options.get("only", False) namemap = options.get("with", {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) # End exact copy from do_include_node() nodelist = parser.parse(("endembed", )) parser.delete_first_token() return EmbedNode( parser.compile_filter(bits[1]), nodelist, extra_context=namemap, isolated_context=isolated_context, )
def include_compressed(parser, token): bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0]) compress_types = ['js', 'css', 'html'] options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'only': value = True elif option in compress_types: unused = compress_types.copy() unused.remove(option) for t in unused: options[t] = False value = True options['type'] = option else: raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value if not "type" in options: TemplateSyntaxError("'html','css' or 'js' not specified " "for %r tag." % bits[0]) compress_type = options.get('type', 'html') isolated_context = options.get('only', False) namemap = options.get('with', {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) return CompressedIncludeNode(parser.compile_filter(bits[1]), extra_context=namemap, isolated_context=isolated_context, compress_type=compress_type)
def include_compressed(parser, token): bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0] ) compress_types = ['js', 'css', 'html'] options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'only': value = True elif option in compress_types: unused = compress_types.copy() unused.remove(option) for t in unused: options[t] = False value = True options['type'] = option else: raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value if not "type" in options: TemplateSyntaxError("'html','css' or 'js' not specified " "for %r tag." % bits[0]) compress_type = options.get('type', 'html') isolated_context = options.get('only', False) namemap = options.get('with', {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) return CompressedIncludeNode(parser.compile_filter(bits[1]), extra_context=namemap, isolated_context=isolated_context, compress_type=compress_type)
def do_extends(parser, token): """ A copy of Django's built-in {% extends ... %} tag that uses our custom ExtendsNode to allow us to load dummy context for the pattern library. """ bits = token.split_contents() if len(bits) != 2: raise TemplateSyntaxError("'%s' takes one argument" % bits[0]) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) parent_name = parser.compile_filter(bits[1]) nodelist = parser.parse() if nodelist.get_nodes_by_type(ExtendsNode): raise TemplateSyntaxError( "'%s' cannot appear more than once in the same template" % bits[0]) return ExtendsNode(nodelist, parent_name)
def do_include_with(parser, token): """ Include template with object attributes injected to context. It takes object and template path as arguments. Object should have template_exposed_attributes list defined. .. code-block:: text {% include_with obj 'path/to/included/template.html' %} It is also possible to overvrite / add additional kwaegs. .. code-block:: text {% include_with obj 'path/to/included/template.html' foo='bar'%} """ bits = token.split_contents() if django_version[0] >= 2: options = parse_bits( parser, bits[1:], ['with_object', 'template_name'], False, True, None, [], None, False, 'include_with', ) else: options = parse_bits( parser, bits[1:], ['with_object', 'template_name'], False, True, None, False, 'include_with', ) bits[2] = construct_relative_path(parser.origin.template_name, bits[2]) template_filter = parser.compile_filter(bits[2]) return IncludeWithNode(bits[1], template_filter, extra_context=options[1])
def do_include(parser, token): """ Loads a template and renders it with the current context. You can pass additional context using keyword arguments. Example:: {% include "foo/some_include" %} {% include "foo/some_include" with bar="BAZZ!" baz="BING!" %} Use the ``only`` argument to exclude the current context when rendering the included template:: {% include "foo/some_include" only %} {% include "foo/some_include" with bar="1" only %} """ bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError( "%r tag takes at least one argument: the name of the template to " "be included." % bits[0]) site = Site.objects.get_current() bits[1] = '"{0}/{1}"'.format(site.domain, bits[1].strip("'").strip('"')) options = {} remaining_bits = bits[2:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = token_kwargs(remaining_bits, parser, support_legacy=False) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'only': value = True else: raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value isolated_context = options.get('only', False) namemap = options.get('with', {}) bits[1] = construct_relative_path(parser.origin.template_name, bits[1]) return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap, isolated_context=isolated_context)
def render(self, context): """ Partly ripped from django.template.loader_tags.IncludeNode """ template_name = self.template_name.resolve(context) template_name = construct_relative_path(self.origin_template_name, template_name) template = get_template(template_name) # Does this quack like a Template? if not callable(getattr(template, 'render', None)): raise TypeError("Must have .render(...) method") # end def values = { name: var.resolve(context) for name, var in self.name_map.items() } if self.isolated_context: return template.render(context.new(values)) with context.push(**values): return template.render(context)
def construct_relative_path_(parser, name): return construct_relative_path(parser.origin.template_name, name)
def construct_relative_path_(parser, name): return construct_relative_path(parser.origin.template_name, name)