2016-10-19 4 views
0

Сегодня у меня возникла странная проблема в одном из моих разработок. Я воспроизвел его с минимальным примером. Посмотрите на эти 2 фиктивных классов (не модели Django подклассы):Django templates: почему метод __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__() метод.

Я хочу, чтобы отобразить экземпляры этих 2-х объектов в представлении через встроенный 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> 

я получить этот результат:

html result

При отображении в позиции второго класса ({{ element }}), вместо __repr__() выполняется метод __call__, и когда я хочу получить доступ к члену класса, он ничего не возвращает.

Я не понимаю, почему определение __call__() изменяет способ обработки шаблонов Django. Я предполагаю, что это не ошибка, а главным образом функция, но мне любопытно, почему в этом случае работает __call__(). И почему я не могу получить значение element.name во втором списке?

ответ

1

Потому что это то, что предназначен для создания шаблона. Как the docs state:

Если вызываемое значение [поиска по переменной] является вызываемым, оно вызывается без аргументов. Результатом вызова становится значение шаблона.

Без этого в шаблонах не будет способа вызова методов, поскольку синтаксис шаблона не позволяет использовать круглые скобки.

+0

Благодарим вас, что это имеет смысл – Antwane