diff --git a/AUTHORS b/AUTHORS index 88dbef908e..52d4950e4e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -83,6 +83,7 @@ answer newbie questions, and generally made Django that much better: Simon Greenhill Espen Grindhaug Brant Harris + Hawkeye heckj@mac.com Joel Heenan hipertracker@gmail.com @@ -116,6 +117,7 @@ answer newbie questions, and generally made Django that much better: mark@junklight.com mattycakes@gmail.com Jason McBrayer + mccutchen@gmail.com michael.mcewan@gmail.com mmarshall Eric Moritz diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html index e5bda0f0e6..0773132cec 100644 --- a/django/contrib/admin/templates/admin/login.html +++ b/django/contrib/admin/templates/admin/login.html @@ -19,7 +19,7 @@
- {% comment %}{% trans 'Have you forgotten your password?' %}{% endcomment %} + {#{% trans 'Have you forgotten your password?' %}#}
diff --git a/django/template/__init__.py b/django/template/__init__.py index af8f37a474..60526b663d 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -66,6 +66,7 @@ __all__ = ('Template', 'Context', 'RequestContext', 'compile_string') TOKEN_TEXT = 0 TOKEN_VAR = 1 TOKEN_BLOCK = 2 +TOKEN_COMMENT = 3 # template syntax constants FILTER_SEPARATOR = '|' @@ -75,6 +76,8 @@ BLOCK_TAG_START = '{%' BLOCK_TAG_END = '%}' VARIABLE_TAG_START = '{{' VARIABLE_TAG_END = '}}' +COMMENT_TAG_START = '{#' +COMMENT_TAG_END = '#}' SINGLE_BRACE_START = '{' SINGLE_BRACE_END = '}' @@ -85,8 +88,9 @@ ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01 UNKNOWN_SOURCE="<unknown source>" # match a variable or block tag and capture the entire tag, including start/end delimiters -tag_re = re.compile('(%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), - re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END))) +tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), + re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END), + re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))) # global dictionary of libraries that have been loaded using get_library libraries = {} @@ -163,12 +167,12 @@ def compile_string(template_string, origin): class Token(object): def __init__(self, token_type, contents): - "The token_type must be TOKEN_TEXT, TOKEN_VAR or TOKEN_BLOCK" + "The token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT" self.token_type, self.contents = token_type, contents def __str__(self): return '<%s token: "%s...">' % \ - ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type], + ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type], self.contents[:20].replace('\n', '')) def split_contents(self): @@ -191,6 +195,8 @@ class Lexer(object): token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip()) elif token_string.startswith(BLOCK_TAG_START): token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip()) + elif token_string.startswith(COMMENT_TAG_START): + token = Token(TOKEN_COMMENT, '') else: token = Token(TOKEN_TEXT, token_string) return token diff --git a/docs/templates.txt b/docs/templates.txt index b263a64aec..0f0009b495 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -109,6 +109,21 @@ Some tags require beginning and ending tags (i.e. below describes all the built-in tags. You can create your own tags, if you know how to write Python code. +Comments +======== + +**New in Django development version** + +To comment-out part of a template, use the comment syntax: ``{# #}``. + +For example, this template would render as ``'hello'``:: + + {# greeting #}hello + +A comment can contain any template code, invalid or not. For example:: + + {# {% if foo %}bar{% else %} #} + Template inheritance ==================== diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index e46b715490..ef31b853ca 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -173,6 +173,22 @@ class Templates(unittest.TestCase): # Empty strings can be passed as arguments to filters 'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'), + ### COMMENT SYNTAX ######################################################## + 'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"), + 'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"), + + # Comments can contain invalid stuff. + 'comment-syntax03': ("foo{# {% if %} #}", {}, "foo"), + 'comment-syntax04': ("foo{# {% endblock %} #}", {}, "foo"), + 'comment-syntax05': ("foo{# {% somerandomtag %} #}", {}, "foo"), + 'comment-syntax06': ("foo{# {% #}", {}, "foo"), + 'comment-syntax07': ("foo{# %} #}", {}, "foo"), + 'comment-syntax08': ("foo{# %} #}bar", {}, "foobar"), + 'comment-syntax09': ("foo{# {{ #}", {}, "foo"), + 'comment-syntax10': ("foo{# }} #}", {}, "foo"), + 'comment-syntax11': ("foo{# { #}", {}, "foo"), + 'comment-syntax12': ("foo{# } #}", {}, "foo"), + ### COMMENT TAG ########################################################### 'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"), 'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"), @@ -473,7 +489,7 @@ class Templates(unittest.TestCase): 'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'), ### HANDLING OF TEMPLATE_TAG_IF_INVALID ################################### - + 'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')), 'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')), 'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''), @@ -606,20 +622,20 @@ class Templates(unittest.TestCase): # Turn TEMPLATE_DEBUG off, because tests assume that. old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False - - # Set TEMPLATE_STRING_IF_INVALID to a known string + + # Set TEMPLATE_STRING_IF_INVALID to a known string old_invalid = settings.TEMPLATE_STRING_IF_INVALID - + for name, vals in tests: install() - + if isinstance(vals[2], tuple): normal_string_result = vals[2][0] invalid_string_result = vals[2][1] else: normal_string_result = vals[2] invalid_string_result = vals[2] - + if 'LANGUAGE_CODE' in vals[1]: activate(vals[1]['LANGUAGE_CODE']) else: @@ -636,10 +652,10 @@ class Templates(unittest.TestCase): continue if output != result: failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output)) - + if 'LANGUAGE_CODE' in vals[1]: deactivate() - + loader.template_source_loaders = old_template_loaders deactivate() settings.TEMPLATE_DEBUG = old_td