diff options
| author | Luke Plant <L.Plant.98@cantab.net> | 2011-04-19 22:06:19 +0000 |
|---|---|---|
| committer | Luke Plant <L.Plant.98@cantab.net> | 2011-04-19 22:06:19 +0000 |
| commit | 1286d783110e8b4d1df8068ed0d9093b49cdcaec (patch) | |
| tree | 0cbaaad3f19a45763e402988130906678f68f09b /tests | |
| parent | 9587235530b5e3315e3348b1e0d0899ec5408f6d (diff) | |
Fixed #15791 - method to signal that callable objects should not be called in templates
Thanks to ejucovy for the suggestion and patch!
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16045 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/regressiontests/templates/callables.py | 111 | ||||
| -rw-r--r-- | tests/regressiontests/templates/tests.py | 1 |
2 files changed, 112 insertions, 0 deletions
diff --git a/tests/regressiontests/templates/callables.py b/tests/regressiontests/templates/callables.py new file mode 100644 index 0000000000..8afa703f63 --- /dev/null +++ b/tests/regressiontests/templates/callables.py @@ -0,0 +1,111 @@ +from django import template +from django.utils.unittest import TestCase + +class CallableVariablesTests(TestCase): + + def test_callable(self): + + class Doodad(object): + def __init__(self, value): + self.num_calls = 0 + self.value = value + def __call__(self): + self.num_calls += 1 + return {"the_value": self.value} + + my_doodad = Doodad(42) + c = template.Context({"my_doodad": my_doodad}) + + # We can't access ``my_doodad.value`` in the template, because + # ``my_doodad.__call__`` will be invoked first, yielding a dictionary + # without a key ``value``. + t = template.Template('{{ my_doodad.value }}') + self.assertEqual(t.render(c), u'') + + # We can confirm that the doodad has been called + self.assertEqual(my_doodad.num_calls, 1) + + # But we can access keys on the dict that's returned + # by ``__call__``, instead. + t = template.Template('{{ my_doodad.the_value }}') + self.assertEqual(t.render(c), u'42') + self.assertEqual(my_doodad.num_calls, 2) + + def test_alters_data(self): + + class Doodad(object): + alters_data = True + def __init__(self, value): + self.num_calls = 0 + self.value = value + def __call__(self): + self.num_calls += 1 + return {"the_value": self.value} + + my_doodad = Doodad(42) + c = template.Context({"my_doodad": my_doodad}) + + # Since ``my_doodad.alters_data`` is True, the template system will not + # try to call our doodad but will use TEMPLATE_STRING_IF_INVALID + t = template.Template('{{ my_doodad.value }}') + self.assertEqual(t.render(c), u'') + t = template.Template('{{ my_doodad.the_value }}') + self.assertEqual(t.render(c), u'') + + # Double-check that the object was really never called during the + # template rendering. + self.assertEqual(my_doodad.num_calls, 0) + + def test_do_not_call(self): + + class Doodad(object): + do_not_call_in_templates = True + def __init__(self, value): + self.num_calls = 0 + self.value = value + def __call__(self): + self.num_calls += 1 + return {"the_value": self.value} + + my_doodad = Doodad(42) + c = template.Context({"my_doodad": my_doodad}) + + # Since ``my_doodad.do_not_call_in_templates`` is True, the template + # system will not try to call our doodad. We can access its attributes + # as normal, and we don't have access to the dict that it returns when + # called. + t = template.Template('{{ my_doodad.value }}') + self.assertEqual(t.render(c), u'42') + t = template.Template('{{ my_doodad.the_value }}') + self.assertEqual(t.render(c), u'') + + # Double-check that the object was really never called during the + # template rendering. + self.assertEqual(my_doodad.num_calls, 0) + + def test_do_not_call_and_alters_data(self): + # If we combine ``alters_data`` and ``do_not_call_in_templates``, the + # ``alters_data`` attribute will not make any difference in the + # template system's behavior. + + class Doodad(object): + do_not_call_in_templates = True + alters_data = True + def __init__(self, value): + self.num_calls = 0 + self.value = value + def __call__(self): + self.num_calls += 1 + return {"the_value": self.value} + + my_doodad = Doodad(42) + c = template.Context({"my_doodad": my_doodad}) + + t = template.Template('{{ my_doodad.value }}') + self.assertEqual(t.render(c), u'42') + t = template.Template('{{ my_doodad.the_value }}') + self.assertEqual(t.render(c), u'') + + # Double-check that the object was really never called during the + # template rendering. + self.assertEqual(my_doodad.num_calls, 0) diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index dedd7d5c92..75f3b4f412 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -25,6 +25,7 @@ from django.utils.translation import activate, deactivate, ugettext as _ from django.utils.safestring import mark_safe from django.utils.tzinfo import LocalTimezone +from callables import * from context import ContextTests from custom import CustomTagTests, CustomFilterTests from parser import ParserTests |
