2016-10-19 22 views
0

今天,我面臨一個奇怪的問題,我的發展之一。我用一個非常簡單的例子重現了它。看看這2個虛擬類(非Django的模型子類):Django模板:爲什麼__call__ magic方法會中斷非模型對象的渲染?

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模板引擎在一個視圖中顯示這2名對象的實例:

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> 

我獲得此結果:

html result

當顯示在第二類的姿勢({{ element }}),__call__方法被執行而不是__repr__(),並且當我想訪問該類的成員時,它不返回任何內容。

我不明白爲什麼定義__call__()改變了Django模板引擎處理這些實例的方式。我想這不是一個錯誤,但主要是一個功能,但我很好奇,爲什麼__call__()在這種情況下運行。爲什麼我不能在第二個列表中獲得element.name的價值?

回答

1

因爲這就是模板語言的設計目的。 As the docs state

如果[查找變量]的結果值是可調用的,則不調用它。該調用的結果成爲模板值。

如果沒有這個,將無法在模板中調用方法,因爲模板語法不允許使用圓括號。

+0

謝謝,這完全有道理 – Antwane