1
0
mirror of https://github.com/django/django.git synced 2025-06-08 13:09:13 +00:00

Fixed #14502 -- Added a verbatim template tag.

Thanks SmileyChris for the patch.
This commit is contained in:
Aymeric Augustin 2012-06-07 09:59:14 +02:00
parent 2c57809a56
commit 4464bbba15
5 changed files with 86 additions and 3 deletions

View File

@ -184,6 +184,7 @@ class Lexer(object):
self.template_string = template_string self.template_string = template_string
self.origin = origin self.origin = origin
self.lineno = 1 self.lineno = 1
self.verbatim = False
def tokenize(self): def tokenize(self):
""" """
@ -203,15 +204,26 @@ class Lexer(object):
If in_tag is True, we are processing something that matched a tag, If in_tag is True, we are processing something that matched a tag,
otherwise it should be treated as a literal string. otherwise it should be treated as a literal string.
""" """
if in_tag: if in_tag and token_string.startswith(BLOCK_TAG_START):
# The [2:-2] ranges below strip off *_TAG_START and *_TAG_END. # The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.
# We could do len(BLOCK_TAG_START) to be more "correct", but we've # We could do len(BLOCK_TAG_START) to be more "correct", but we've
# hard-coded the 2s here for performance. And it's not like # hard-coded the 2s here for performance. And it's not like
# the TAG_START values are going to change anytime, anyway. # the TAG_START values are going to change anytime, anyway.
block_content = token_string[2:-2].strip()
if self.verbatim and block_content == self.verbatim:
self.verbatim = False
if in_tag and not self.verbatim:
if token_string.startswith(VARIABLE_TAG_START): if token_string.startswith(VARIABLE_TAG_START):
token = Token(TOKEN_VAR, token_string[2:-2].strip()) token = Token(TOKEN_VAR, token_string[2:-2].strip())
elif token_string.startswith(BLOCK_TAG_START): elif token_string.startswith(BLOCK_TAG_START):
token = Token(TOKEN_BLOCK, token_string[2:-2].strip()) if block_content.startswith('verbatim'):
bits = block_content.split(' ', 1)
if bits[0] == 'verbatim':
if len(bits) > 1:
self.verbatim = bits[1]
else:
self.verbatim = 'endverbatim'
token = Token(TOKEN_BLOCK, block_content)
elif token_string.startswith(COMMENT_TAG_START): elif token_string.startswith(COMMENT_TAG_START):
content = '' content = ''
if token_string.find(TRANSLATOR_COMMENT_MARK): if token_string.find(TRANSLATOR_COMMENT_MARK):

View File

@ -6,7 +6,7 @@ from datetime import datetime
from itertools import groupby, cycle as itertools_cycle from itertools import groupby, cycle as itertools_cycle
from django.conf import settings from django.conf import settings
from django.template.base import (Node, NodeList, Template, Library, from django.template.base import (Node, NodeList, Template, Context, Library,
TemplateSyntaxError, VariableDoesNotExist, InvalidTemplateLibrary, TemplateSyntaxError, VariableDoesNotExist, InvalidTemplateLibrary,
BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END,
SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END,
@ -425,6 +425,13 @@ class URLNode(Node):
else: else:
return url return url
class VerbatimNode(Node):
def __init__(self, content):
self.content = content
def render(self, context):
return self.content
class WidthRatioNode(Node): class WidthRatioNode(Node):
def __init__(self, val_expr, max_expr, max_width): def __init__(self, val_expr, max_expr, max_width):
self.val_expr = val_expr self.val_expr = val_expr
@ -1272,6 +1279,32 @@ def url(parser, token):
return URLNode(viewname, args, kwargs, asvar) return URLNode(viewname, args, kwargs, asvar)
@register.tag
def verbatim(parser, token):
"""
Stops the template engine from rendering the contents of this block tag.
Usage::
{% verbatim %}
{% don't process this %}
{% endverbatim %}
You can also specify an alternate closing tag::
{% verbatim -- %}
...
{% -- %}
"""
bits = token.contents.split(' ', 1)
if len(bits) > 1:
closing_tag = bits[1]
else:
closing_tag = 'endverbatim'
nodelist = parser.parse((closing_tag,))
parser.delete_first_token()
return VerbatimNode(nodelist.render(Context()))
@register.tag @register.tag
def widthratio(parser, token): def widthratio(parser, token):
""" """

View File

@ -1040,6 +1040,29 @@ This will follow the normal :ref:`namespaced URL resolution strategy
<topics-http-reversing-url-namespaces>`, including using any hints provided <topics-http-reversing-url-namespaces>`, including using any hints provided
by the context as to the current application. by the context as to the current application.
.. templatetag:: verbatim
verbatim
^^^^^^^^
.. versionadded:: 1.5
Stops the template engine from rendering the contents of this block tag.
A common use is to allow a Javascript template layer that collides with
Django's syntax. For example::
{% verbatim %}
{{if dying}}Still alive.{{/if}}
{% endverbatim %}
You can also specify an alternate closing tag::
{% verbatim finished %}
The verbatim tag looks like this:
{% verbatim %}{% endverbatim %}
{% finished %}
.. templatetag:: widthratio .. templatetag:: widthratio
widthratio widthratio

View File

@ -62,6 +62,13 @@ For one-to-one relationships, both sides can be cached. For many-to-one
relationships, only the single side of the relationship can be cached. This relationships, only the single side of the relationship can be cached. This
is particularly helpful in combination with ``prefetch_related``. is particularly helpful in combination with ``prefetch_related``.
``{% verbatim %}`` template tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To make it easier to deal with javascript templates which collide with Django's
syntax, you can now use the :ttag:`verbatim` block tag to avoid parsing the
tag's content.
Minor features Minor features
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~

View File

@ -1616,6 +1616,14 @@ class Templates(unittest.TestCase):
'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL), 'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),
'static-statictag01': ('{% load static %}{% static "admin/base.css" %}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')), 'static-statictag01': ('{% load static %}{% static "admin/base.css" %}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')),
'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')), 'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')),
# Verbatim template tag outputs contents without rendering.
'verbatim-tag01': ('{% verbatim %}{{bare }}{% endverbatim %}', {}, '{{bare }}'),
'verbatim-tag02': ('{% verbatim %}{% endif %}{% endverbatim %}', {}, '{% endif %}'),
'verbatim-tag03': ("{% verbatim %}It's the {% verbatim %} tag{% endverbatim %}", {}, "It's the {% verbatim %} tag"),
'verbatim-tag04': ('{% verbatim %}{% verbatim %}{% endverbatim %}{% endverbatim %}', {}, template.TemplateSyntaxError),
'verbatim-tag05': ('{% verbatim %}{% endverbatim %}{% verbatim %}{% endverbatim %}', {}, ''),
'verbatim-tag06': ("{% verbatim -- %}Don't {% endverbatim %} just yet{% -- %}", {}, "Don't {% endverbatim %} just yet"),
} }
return tests return tests