Code

Ticket #16307: 16307_test_callable_variable_attribute_parsing.diff

File 16307_test_callable_variable_attribute_parsing.diff, 2.3 KB (added by rico, 3 years ago)

Tests and fix for accessing attributes on callables and classes

Line 
1diff --git a/django/template/base.py b/django/template/base.py
2index 49ef0b8..306f549 100644
3--- a/django/template/base.py
4+++ b/django/template/base.py
5@@ -690,7 +690,7 @@ class Variable(object):
6                                 TypeError,  # unsubscriptable object
7                                 ):
8                             raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute
9-                if callable(current):
10+                if callable(current) and not isinstance(current, type):
11                     if getattr(current, 'alters_data', False):
12                         current = settings.TEMPLATE_STRING_IF_INVALID
13                     else:
14diff --git a/tests/regressiontests/templates/parser.py b/tests/regressiontests/templates/parser.py
15index 1609c67..a800fd6 100644
16--- a/tests/regressiontests/templates/parser.py
17+++ b/tests/regressiontests/templates/parser.py
18@@ -81,3 +81,36 @@ class ParserTests(TestCase):
19         self.assertRaises(TemplateSyntaxError,
20             Variable, "article._hidden"
21         )
22+
23+    def test_callable_variable_attribute_parsing(self):
24+        # Test for ticket https://code.djangoproject.com/ticket/16307
25+
26+        # Classes shouldn't be treated as callables.
27+        # Using a required argument to force a failure when calling.
28+
29+        # Class methods and static methods should get called normally.
30+        class SomeClass(object):
31+            verbose_name = "Some Class"
32+
33+            def __init__(self, required_arg):
34+                pass
35+
36+            @classmethod
37+            def class_method(cls):
38+                return 'class method'
39+
40+            @staticmethod
41+            def static_method():
42+                return 'static method'
43+
44+        # A simple function should get called normally
45+        def some_function():
46+            return {"verbose_name": "some function"}
47+
48+        c = {"some_class": SomeClass, "some_function": some_function}
49+
50+        self.assertEqual(Variable("some_class.verbose_name").resolve(c), "Some Class")
51+        self.assertEqual(Variable("some_class.class_method").resolve(c), "class method")
52+        self.assertEqual(Variable("some_class.static_method").resolve(c), "static method")
53+        self.assertEqual(Variable("some_function.verbose_name").resolve(c), "some function")
54+