У цій статті розповім про те, як саме можна написати простий блоковий шаблонний тег, на кшталт тега blocktranslate у Django .
Такі блокові шаблонні теги мають тег, що відкриває і закриває тег, і найбільш часто зустрічається я б назвав тег blocktranslate , який дозволяє перекладати цілий шматки коду html, а не тільки окремі пропозиції. Виглядати такий тег буде наступним чином.
{% blocktranslate %}This string will have {{ value }} inside.{% endblocktranslate %}
У даному випадку тег має тег, що відкриває blocktranslate і закриває тег endblocktranslate , а з контентом усередині відбувається певна маніпуляція.
Особисто я написав кілька простих тегів для спрощення написання коду шаблонів на сайті. Одним з таких тегів є тег tabber усередині якого я також використовую теги tab_item .
Це скорочує написання коду в шаблонах і робить шаблон більш доброзичливим і більш легко піддається підтримці.
У результаті код шаблону у мене може мати такий вигляд.
{% load tabbar tab_item from myapp %} {% url 'myapp:settings_main' as the_settings_main_url %} {% url 'myapp:settings_notification' as the_settings_notification_url %} {% tabbar %} {% tab_item _('Main') the_settings_main_url True %} {% tab_item _('Notifications') the_settings_notification_url %} {% end_tabbar %}
В результаті дані шаблонні теги генерують наступний HTML код
<div class="overflow-hidden"> <div class="nav nav-tabs border-bottom flex-nowrap"> <a class="text-nowrap nav-item nav-link active" href="/ru/myapp/settings/main/">Основное</a> <a class="text-nowrap nav-item nav-link" href="/ru/myapp/settings/notification/">Уведомления</a> </div> </div>
Як бачите, тут генерується досить стандартний для bootstrap код Tab Bar.
І якщо цей конкретний випадок можливо не є чимось, що може вимагати написання такого тега, то знання, як написати подібний тег може стати в нагоді в більш складних варіантах верстки, або там, де на сайті багато місць використання подібних табів. Що буде дуже корисно, оскільки для зміни верстки у всіх частинах сайту достатньо буде змінити лише код цих шаблонних тегів.
А тепер приступимо до вивчення, як написати такий шаблонний тег.
Структура програми
Допустимо у нас є додаток myapp , який міститиме дані шаблонні теги. Для цього необхідно, щоб у цьому додатку були створені директорії та файли з наступною структурою (крім тих, що створюються за замовчуванням)
-
myapp
-
templates
-
myapp
- tabbar.html
- tab_item.html
-
myapp
-
templatetages
- __init__.py
- myapp.py
-
templates
тег tabbar у файлі myapp.py
Даний файл буде містити python код для обробки тега в шаблоні, а також поруч з ним знаходиться файл init .py, який ініціалізує myapp в директорії templatetags як бібліотека тегів. За замовчуванням файл порожній, але він там потрібен.
Для початку додамо необхідні імпорти
# -*- coding: utf-8 -*- import random from django import template from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ register = template.Library()
Після цього зареєструємо шаблонний тег. Важливий момент полягає в тому, що зазвичай функції, які реєструються як блоковий шаблонний тег, починаються з префікса do_ . Як бачите в коді нижче, як тільки парсер Django знаходить тег {% tabbar %}, то він відразу починає парсить шаблон у вигляді списку нод, тега, що закриває, який в даному випадку названий end_tabbar , при цьому перший токен з парсер видаляється. Як я зрозумів це видаляється нода, всередині якої був знайдений tabbar тег, в результаті він вже не обробляється. Список нод передається в кастомний клас ноди (TabBarNode) для подальшої обробки.
@register.tag("tabbar") def do_tabbar(parser, token): tag_name, args, kwargs = parse_tag(token, parser) nodelist = parser.parse(('end_tabbar',)) parser.delete_first_token() return TabBarNode(nodelist)
Далі за обробку приймається клас
TabBarNode
, який ініціалізується списком нод (nodelist), що рендерується у змінну
tabbar_content
. Метод render викликає подальший парсинг всіх інших нод, поки всі ноди не розпарсуються і не відрендеряться до стану звичайного рядка, який можна вставити у вигляді змінної tabbar_content шаблон і відрендерити за допомогою функції
render_to_string
у методі
render
. Ви помітили, що
nodelist також має метод
render
?
class TabBarNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist def render(self, context): context.update({'tabbar_content': self.nodelist.render(context)}) return render_to_string( template_name='myapp/tabbar.html', context=context.flatten() )
tabbar.html
Шаблон у разі виглядає досить тривіально.
<div class="overflow-hidden"> <div class="nav nav-tabs border-bottom flex-nowrap"> {{ tabbar_content }} </div> </div>
тег tab_item в файле myapp.py
А ось tab_item реєструємо вже як inclusion_tag , і для розуміння він уже більш простий.
Тут є вхідні аргументи, які відповідають за:
- Текст
- Посилання
- Вказівка css активності посилання
@register.inclusion_tag('myapp/tab_item.html', takes_context=True) def tab_item(context, title, url='#', active=False): return { 'title': title, 'url': url, 'active': active, }
tab_item.html
І поглянемо на шаблон тега
<a class="text-nowrap nav-item nav-link{% if active %} active{% endif %}" href="{{ url }}">{{ title }}</a>
Висновок
В результаті вийшов невеликий спрощений спосіб написання TabBar на сайті за допомогою блокових тегів.
Хорошая статья. И тут я подумал что на её основе можно отлично сформировать "хлебные крошки". Самое простое распарсить адрес. Так и поступил бы но лень
Почитайте эту статью про "хлебные крошки"
Да не я так к примеру просто написал.