diff --git a/django/template/__init__.py b/django/template/__init__.py index c5b8ba0b8f..503cfb77bf 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -445,16 +445,17 @@ class TokenParser(object): self.pointer = i return s +# This only matches constant *strings* (things in quotes or marked for +# translation). Numbers are treated as variables for implementation reasons +# (so that they retain their type when passed to filters). constant_string = r""" (?:%(i18n_open)s%(strdq)s%(i18n_close)s| %(i18n_open)s%(strsq)s%(i18n_close)s| %(strdq)s| -%(strsq)s)| -%(num)s +%(strsq)s) """ % { 'strdq': r'"[^"\\]*(?:\\.[^"\\]*)*"', # double-quoted string 'strsq': r"'[^'\\]*(?:\\.[^'\\]*)*'", # single-quoted string - 'num': r'[-+\.]?\d[\d\.e]*', # numeric constant 'i18n_open' : re.escape("_("), 'i18n_close' : re.escape(")"), } @@ -462,17 +463,18 @@ constant_string = constant_string.replace("\n", "") filter_raw_string = r""" ^(?P%(constant)s)| -^(?P[%(var_chars)s]+)| +^(?P[%(var_chars)s]+|%(num)s)| (?:%(filter_sep)s (?P\w+) (?:%(arg_sep)s (?: (?P%(constant)s)| - (?P[%(var_chars)s]+) + (?P[%(var_chars)s]+|%(num)s) ) )? )""" % { 'constant': constant_string, + 'num': r'[-+\.]?\d[\d\.e]*', 'var_chars': "\w\." , 'filter_sep': re.escape(FILTER_SEPARATOR), 'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR), diff --git a/tests/regressiontests/templates/custom.py b/tests/regressiontests/templates/custom.py new file mode 100644 index 0000000000..e83b7dc736 --- /dev/null +++ b/tests/regressiontests/templates/custom.py @@ -0,0 +1,11 @@ +from django import test +from django import template + + +custom_filters = """ +>>> t = template.Template("{% load custom %}{{ string|trim:5 }}") +>>> ctxt = template.Context({"string": "abcdefghijklmnopqrstuvwxyz"}) +>>> t.render(ctxt) +u"abcde" +""" + diff --git a/tests/regressiontests/templates/templatetags/__init__.py b/tests/regressiontests/templates/templatetags/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regressiontests/templates/templatetags/custom.py b/tests/regressiontests/templates/templatetags/custom.py new file mode 100644 index 0000000000..fdf8d1077f --- /dev/null +++ b/tests/regressiontests/templates/templatetags/custom.py @@ -0,0 +1,11 @@ +from django import template +from django.template.defaultfilters import stringfilter + +register = template.Library() + +def trim(value, num): + return value[:num] +trim = stringfilter(trim) + +register.filter(trim) + diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 2211ac77be..f0eee526cc 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -18,9 +18,10 @@ from django.utils.translation import activate, deactivate, ugettext as _ from django.utils.safestring import mark_safe from django.utils.tzinfo import LocalTimezone -from unicode import unicode_tests from context import context_tests +from custom import custom_filters from parser import filter_parsing, variable_parsing +from unicode import unicode_tests try: from loaders import * @@ -34,6 +35,7 @@ __test__ = { 'unicode': unicode_tests, 'context': context_tests, 'filter_parsing': filter_parsing, + 'custom_filters': custom_filters, } #################################