2014-12-05 3 views
1

Im ищет элегантное решение для моего дизайна шаблона в django. Я стараюсь сделать минималистский пример:Django - Templatetags, include и класс hierachy

На странице представлены разные функциональные области, например поле новостей и опрос, представленный собственными приложениями в django. Число этих областей совершенно иное, поэтому могут быть, например, три опроса и два поля новостей в определенном порядке (не отсортированы по типу).
Так вот пример реализации, как я бы решить эту проблему:

# in main app: 
class Field(models.Model): 
... 

# in polls app: 
class Poll(main.models.Field): 
... 

И для различного рода опросов:

class PrivatePoll(Poll): 
... 

Система шаблонов может затем перебирать объекты типа Field.

{% for field in fields %} 
    {% show_field field %} 
{% endfor %} 

Но моя проблема в том, что каждый подкласс поля или подкласса Poll нужен свой собственный способ отображения содержимого. Я знаю о templatetagвключение функция в Django, но templatetag затем должен различать подклассы и как их отображать ... Я хотел бы увидеть «код шаблона» каждого приложения внутри самого приложения, но я не получаю хорошее решение.

Что можно сказать о включают тег начиная с Django 1.7, который может представлять собой способ с визуализации()? Итак, что все классы и подклассы имеют метод render()? Я не понимаю, как использовать эту новую функциональность.

Любые идеи, как я могу это решить? Модели не должны быть подклассами, может быть, лучше иметь OneToOneRelationship s или что-то еще?

редактировать:
Могу ли я использовать включают тег, как это? Это хороший стиль джанго?

{% for field in fields %} 
    {% include field.render %} 
{% endfor %} 

edit2:
я написал свой собственный шаблонный тег, как вышеписанной документации. Но это правильный способ сделать это?

from django import template 
from django.template.loader import render_to_string 

register = template.Library() 

@register.tag 
def display_object(parser, token): 
    try: 
     tag_name, tile_object, template_to_render = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError("%r tag requires exactly two arguments" % token.contents.split()[0]) 
    return MyNode(tile_object, template_to_render) 


class MyNode(template.Node): 
    def __init__(self, tile_object, template_to_render): 
     self.tile_object = template.Variable(tile_object) 
     self.template_to_render = template_to_render 

    def render(self, context): 
     try: 
      tile_object = self.tile_object.resolve(context) 
      return render_to_string(self.template_to_render, tile_object) 
     except template.VariableDoesNotExist: 
      return '' 

Теперь теоретически я могу использовать его в моем шаблоне:

{% for field in fields %} 
    {% display_object field field.template_to_use %} 
{% endfor %} 

Но он чувствует себя не правильно, особенно display_object(..), где переменные передаются строками ..!? И не сталкивается с этой строкой, если я вызываю display_object с field несколько раз, потому что это всегда одна и та же строка «поле», которая передается ..!?

Все, что я хочу, это отображать шаблоны, указанные в экземпляре объекта, является ли такой трудный способ единственным способом решить эту проблему? Или я должен перестроить свою иерархию по-другому?

Edit3:
Хорошо после того, как много больше исследований, это именно то, что делает include тег (source code). Я не понимаю, почему так много людей (в форумах/на StackOverflow) говорят, что «включить» не следует использовать ...

Итак, наконец, это будет мое решение:

{% for field in fields %} 
    {% include field.template_to_render with context=field.context %} 
{% endfor %} 

Любые предложения?

ответ

0

Как насчет тега include с Django 1.7, который может представлять метод с помощью render()? Итак, что все классы и подклассы имеют метод render()?

От теоретического POV, который был бы нарушением ответственности уровня, поскольку модели предназначены для логики домена, а не для представления. Если «область логики» для моделей не только (или в основном) о представлении, конечно (думаю страницы см или такие)

Но моя проблема в том, что каждый подкласс поля или подкласс Poll нужно их собственный способ отображения содержимого.

Что означает один шаблон для каждого подкласса. Самое простое решение IMHO будет указать путь к шаблонам в качестве атрибута класса моделей, а затем переписать show_field шаблон, чтобы использовать этот шаблон для рендеринга ...

Могу ли я использовать тег включают, как это? Это хороший стиль джанго?

{% для поля в полях%} {% включают field.render%} {%}% ENDFOR

field.render Предполагая, что это метод, который принимает контекст в качестве аргумента, то (технически) правильное использование будет :

{% for field in fields %} 
    {% include field %} 
{% endfor %} 
+0

Но «включить поле» я не должен использовать из-за нарушения, которое вы описали? – FaBay

+0

Хорошо, перепишите 'show_field', но как изменить шаблон для 'include_tag'? Я мог бы вернуть здесь «render_to_string»: [link] (http://stackoverflow.com/questions/17178525/django-how-to-include-a-view-from-within-a-template), но это кажется, не является правильной реализацией. В документации построен «узел» для пользовательских тегов шаблонов ... – FaBay

+0

Динамическое изменение шаблона для 'включения_tag' вы не можете, вам нужно написать весь template_tag (парсер и узел). Но не волнуйтесь, это хорошо документировано (https://docs.djangoproject.com/en/1.7/howto/custom-template-tags/#writing-custom-template-tags) и проще, чем сначала. –