今天我在一个开发项目上遇到了一个奇怪的问题。我用一个非常小的例子再现了它。看看这两个虚拟类(非Django模型子类):
class DummyClassA(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Dummy1 object called ' + self.name
class DummyClassB(object):
"""Same as ClassA, with the __call__ method added"""
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Dummy2 object called ' + self.name
def __call__(self, *args, **kwargs):
return "bar"
它们是相同的,但第二种方法有一种特殊的__call__()
方法。
我想使用内置的Django模板引擎在视图中显示这两个对象的实例:
class MyView(TemplateView):
template_name = 'myapp/home.html'
def get_context_data(self, **kwargs):
ctx = super(MyView, self).get_context_data(**kwargs)
list1 = [
DummyClassA(name="John"),
DummyClassA(name="Jack"),
]
list2 = [
DummyClassB(name="Albert"),
DummyClassB(name="Elmer"),
]
ctx.update({
'list1': list1,
'list2': list2,
})
return ctx
和相应的模板:
<h1>Objects repr</h1>
<ul>
{% for element in list1 %}
<li>{{ element }}</li>
{% endfor %}
</ul>
<ul>
{% for element in list2 %}
<li>{{ element }}</li>
{% endfor %}
</ul>
<h1>Access members</h1>
<ul>
{% for element in list1 %}
<li>{{ element.name }}</li>
{% endfor %}
</ul>
<ul>
{% for element in list2 %}
<li>{{ element.name }}</li>
{% endfor %}
</ul>
我得到了这个结果:
当显示第二个类的实例({{ element }}
)时,执行__call__
方法而不是__repr__()
,当我想访问类的成员时,它不返回任何内容。
我不明白为什么定义__call__()
会改变Django模板引擎处理这些实例的方式。我想这不是一个错误,但主要是一个功能,但我很好奇,为什么__call__()
在这种情况下运行。为什么我无法在第二个列表中获得element.name
的值?
答案 0 :(得分:1)
因为这就是模板语言的设计目的。正如the docs state:
如果[查找变量]的结果值是可调用的,则调用它时不带参数。调用的结果成为模板值。
如果没有这个,就无法在模板中调用方法,因为模板语法不允许使用括号。