Собственно, в джанге в родном шаблонизаторе есть возможность писать свои теги и фильтры.
А вот у меня встала задача. Есть какой-то контент, ну к примеру формируется он так:
# some_template.html ;
<div class="head-ev-bg">
<div class="head-ev-numb">
<div class="ev-character ev-{{ number }}"></div>
</div>
<div class="head-ev-l"></div><div class="head-ev-r"></div>
<div><h4 class="titlec">{{ title }}</h4></div>
</div>
<div class="ev-cont">
<div class="ev-cont-bg">
{{ content }}
</div>
<div class="ev-cont-bt"></div>
</div>
А вот у меня встала задача. Есть какой-то контент, ну к примеру формируется он так:
# some_template.html ;
<div class="head-ev-bg">
<div class="head-ev-numb">
<div class="ev-character ev-{{ number }}"></div>
</div>
<div class="head-ev-l"></div><div class="head-ev-r"></div>
<div><h4 class="titlec">{{ title }}</h4></div>
</div>
<div class="ev-cont">
<div class="ev-cont-bg">
{{ content }}
</div>
<div class="ev-cont-bt"></div>
</div>
Ну вроде бы ничего так. Надо передать какое-то число, заголовок и контент.
Беда в том, что контент - это ещё куча html кода. И вот выше изложенная последовательность повторяется пару раз на странице. Обычный тег должен проглотить контент через параметр.
К примеру:
{% some_tag "number" "title" "content" %}
Всё было бы не плохо, если бы не листинг в две страницы в этом поле "content" ))) Как-то сразу отпадает желание.
Вот и подумалось мне, ну раз есть {% for %} {% endfor %}, то наверное можно так же написать свой собственный тег, тег с закрытием.
А для меня он будет выглядеть так:
{% some_tag "number" "title" %}
content
{% endsome_tag %}
Красиво? Ну вот и я так считаю. Что же, а теперь листинг кода.
from django import template
register = template.Library()
class SomeTagNode(template.Node):
def __init__(self, nodelist, id, title):
self.nodelist = nodelist
self.id = id
self.title = title
def render(self, context):
output = self.nodelist.render(context) # выдаст то, что было между открывающим тегом и закрывающим
t = template.loader.get_template('some_template.html')
c = template.Context({ 'number': self.id, 'title': self.title, 'content': output})
return t.render(c) # формируем шаблон и выводим
def do_sometag(parser, token):
# parser - структура шаблона
# token - то, что передадим тегу в качестве параметров
try:
tag_name, id, title = token.split_contents()
except ValueError:
# Для меня важно получить два параметра
raise template.TemplateSyntaxError("%r tag requires exactly two arguments" % token.contents.split()[0])
# Проверяю, что бы каждый параметр шёл в кавычках
if not (id[0] == id[-1] and id[0] in ('"', "'")):
raise template.TemplateSyntaxError("%r tag's first argument should be in quotes" % tag_name)
if not (title[0] == title[-1] and title[0] in ('"', "'")):
raise template.TemplateSyntaxError("%r tag's second argument should be in quotes" % tag_name)
nodelist = parser.parse(('endsometag',)) # построить структуру до заданного тега
parser.delete_first_token()
return SomeTagNode(nodelist, id[1:-1], title[1:-1]) # отправим струкуру
register.tag('sometag, do_sometag) # загрузим наше представление тега в общую библиотеку
P.S.: Я ничего не сделал того, что не описано в документаци к джанго. Даже более, это есть практически в таком виде в самой документации. Но, почитать и понять придется.
P.P.S.: Для меня это было в качестве упражнения и не более, т.к. html структура была вот такой, какой я её здесь описал. Но, с другой стороны, теперь мне, если придется поменять структуру, то я буду делать это в одном шаблоне, а не в десяти местах в разных шаблонах, что радует.
P.S.: Я ничего не сделал того, что не описано в документаци к джанго. Даже более, это есть практически в таком виде в самой документации. Но, почитать и понять придется.
P.P.S.: Для меня это было в качестве упражнения и не более, т.к. html структура была вот такой, какой я её здесь описал. Но, с другой стороны, теперь мне, если придется поменять структуру, то я буду делать это в одном шаблоне, а не в десяти местах в разных шаблонах, что радует.