Django templates: why does __call__ magic method breaks the rendering of a non-model object?
<p>Today I faced a strange issue on one of my development. I reproduced it with a very minimal example. Have a look at these 2 dummy classes (non Django model subclasses):</p>

<pre><code>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"
</code></pre>

<p>They are identical, but the second have a special <code>__call__()</code> method.</p>

<p>I want to display instances of these 2 objects in a view using the builtin Django template engine:</p>

<pre><code>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
</code></pre>

<p>and the corresponding template:</p>

<pre><code>    &lt;h1&gt;Objects repr&lt;/h1&gt;
    &lt;ul&gt;
        {% for element in list1 %}
            &lt;li&gt;{{ element }}&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
    &lt;ul&gt;
        {% for element in list2 %}
            &lt;li&gt;{{ element }}&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;

    &lt;h1&gt;Access members&lt;/h1&gt;
    &lt;ul&gt;
        {% for element in list1 %}
            &lt;li&gt;{{ element.name }}&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
    &lt;ul&gt;
        {% for element in list2 %}
            &lt;li&gt;{{ element.name }}&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
</code></pre>

<p>I obtain this result:</p>

<p><a href="https://i.stack.imgur.com/kL9lZ.png" rel="nofollow"><img src="https://i.stack.imgur.com/kL9lZ.png" alt="html result"></a></p>

<p>When displaying instances of the second class (<code>{{ element }}</code>), the <code>__call__</code> method is executed instead of <code>__repr__()</code>, and when I want to access a member of the class, it returns nothing. </p>

<p>I don't understand why defining the <code>__call__()</code> change the way Django template engine will handle those instances. I imagine this is not a bug but mostly a feature, but I am curious, why <code>__call__()</code> is run in such case. And why I can't get the value of <code>element.name</code> in the 2nd list ?</p>

<p>Because that's what the template language is designed to do. As <a href="https://docs.djangoproject.com/en/1.10/ref/templates/language/#variables" rel="nofollow">the docs state</a>:</p>

<blockquote>
  <p>If the resulting value [of looking up a variable] is callable, it is called with no arguments. The result of the call becomes the template value.</p>
</blockquote>

<p>Without this, there would be no way of calling methods in templates, since the template syntax does not allow using parentheses.</p>

python django templates magic-methods