Создание тегов шаблонизатора Django

Джанго предоставляет следующие вспомогательные функции, позволяющие создавать собственные теги шаблонов простым способом:

  • simple_tag: обрабатывает данные и возвращает строку
  • inclusion_tag: обрабатывает данные и возвращает обработанный шаблон
  • assignment_tag: обрабатывает данные и задает переменную в контексте

Теги шаблонов должны жить внутри приложений Джанго.

В каталоге приложения блога создайте новый каталог, назовите его templatetags и добавьте в него пустой файл __init__.py Создайте еще один файл в той же папке и назовите его blog_tags.py. Фаловая структура приложения блога должна выглядеть следующим образом:

blog/
    __init__.py
    models.py
    ...
    templatetags/
        __init__.py
        blog_tags.py

Имя файла имеет важное значение. Имя этого модуля будет использоваться для загрузки тегов в шаблоны.

Начнем с создания простого тега, чтобы получить общее количество записей, опубликованных в блоге. Отредактируйте только что созданный файл blog_tags.py и добавьте следующий код:

from django import template

register = template.Library()

from ..models import Post

@register.simple_tag
def total_posts():
    return Post.published.count()

Создан простой тег шаблона, который возвращает количество опубликованных записей. Каждый модуль тегов шаблона должен содержать переменную, называемую register, в качестве допустимой библиотеки тегов. Эта переменная является экземпляром шаблона. Библиотека и используется для регистрации собственных тегов шаблонов и фильтров. Затем мы определим тег с именем total_posts с функцией Python и с помощью функции @register.simple_tag, чтобы определить функцию как простой тег и зарегистрировать ее. Джанго будет использовать имя функции в качестве имени тега. Если требуется зарегистрировать его с другим именем, это можно сделать, указав атрибут name, например @register.simple_tag(name='my_tag').

После добавления нового модуля тегов шаблонов необходимо перезапустить сервер разработки Джанго, чтобы использовать новые теги и фильтры шаблонов.

Перед использованием пользовательских тегов шаблонизатора необходимо сделать их доступными для шаблона с помощью тега {% load %}. Как упоминалось ранее, необходимо использовать имя модуля Python, содержащего теги шаблонов и фильтры. Откройте шаблон blog/base.html и добавьте в его верхнюю часть {% load blog_tags %}, чтобы загрузить модуль тегов шаблонов. Затем используйте созданный тег для отображения количества записей. Просто добавьте в шаблон {% total_posts %}. Шаблон должен выглядеть следующим образом:

{% load blog_tags %}
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
    <link href="{% static "css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="content">
    {% block content %}
    {% endblock %}
</div>
<div id="sidebar">
    <h2>My blog</h2>
    <p>This is my blog. I've written {% total_posts %} posts so far.</p>
</div>
</body>
</html>

Для отслеживания новых файлов, добавленных в проект, необходимо перезагрузить сервер. Остановите сервер разработки с помощью комбинаций клавиш Ctrl+C и запустите его снова, используя эту команду:

python manage.py runserver

Откройте http://127.0.0.1:8000/blog/ в своем браузере. Вы должны увидеть общее количество постов в сайдбаре:

Мощь пользовательских тегов шаблонов заключается в том, что можно обрабатывать любые данные и добавлять их в любой шаблон независимо от выполняемого представления. Можно выполнять QuerySets или обрабатывать любые данные для отображения результатов в шаблонах.

Теперь создадим еще один тег для отображения последних сообщений в боковой панели нашего блога. На этот раз мы будем использовать inclusion_tag. С помощью inclusion_tag можно визуализировать шаблон с переменными контекста, возвращаемыми тегом шаблона. Добавьте следующий код в файл blog_tags.py:

@register.inclusion_tag('blog/post/latest_posts.html')
def show_latest_posts(count=5):
    latest_posts = Post.published.order_by('-publish')[:count]
    return {'latest_posts': latest_posts}

В этом коде мы регистрируем тег шаблона с помощью @register.inclusion_tag, и мы указываем шаблон, который должен быть визуализирован с возвращаемыми значениями в blog/post/latest_posts.html. Тег шаблона будет принимать необязательный параметр count, который по умолчанию имеет значение 5, и позволяет указать количество комментариев, которые требуется отобразить. Эта переменная используется для ограничения результатов запроса Post.published.order_by('-publish')[:count]. Обратите внимание, что функция возвращает словарь вместо простого значения. inclusion_tag должен возвращать словарь значений, используемый в качестве контекста для визуализации указанного шаблона. Теги включения возвращают словарь. Тег шаблона, который мы только что создали, можно использовать для передачи числа комментариев, которые будут отображаться как {% show_latest_posts 3 %}

Теперь создайте файл latest_posts.html в директории blog/post/ и добавьте в него следующий код:

<ul>
    {% for post in latest_posts %}
        <li>
            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
        </li>
    {% endfor %}
</ul>

Здесь отображается неупорядоченный список записей с использованием переменной latest_posts, возвращаемой нашим тегом шаблона. Теперь отредактируйте шаблон blog/base.html и добавьте новый тег шаблона для отображения последних 3 комментариев. Блок боковой панели должен выглядеть следующим образом:

<div id="sidebar">
    <h2>My blog</h2>
    <p>This is my blog. I've written {% total_posts %} posts so far.</p>

    <h3>Latest posts</h3>
    {% show_latest_posts 3 %}
</div>

Тег шаблона вызывается для отображения числа комментариев, а шаблон отображается на месте с заданным контекстом.

Теперь вернитесь в браузер и обновите страницу. Боковая панель должна выглядеть следующим образом:

Наконец, мы собираемся создать assignment_tag. Теги присваивания похожи на простые теги, но они сохраняют результат в заданной переменной. Мы создадим assignment_tag для отображения записей с комментариями. Измените файл blog_tags.py:

from django.db.models import Count

@register.assignment_tag
def get_most_commented_posts(count=5):
    return Post.published.annotate(total_comments=Count('comments')).order_by('-total_comments')[:count]

Этот запрос использует функцию annotate() для агрегирования запросов с помощью статистической функции count. Мы строим запрос, получающий общее количество комментариев для каждой записи в поле total_comments, и сортируем их с помощью функции order_by(). Кроме того, для ограничения общего числа объектов, возвращаемых к заданному значению, также предоставляется необязательная переменная count.

В adition to Count, Джанго предлагает статистические функции Avg , Max , Min , и Sum. Дополнительные сведения об агрегатных функциях можно прочитать здесь: https://docs.djangoproject.com/en/1.8/topics/db/aggregation/

Отредактируйте шаблон blog/base.html и добавьте следующий код к боковой панели:

<h3>Most commented posts</h3>
{% get_most_commented_posts as most_commented_posts %}
<ul>
    {% for post in most_commented_posts %}
        <li>
            <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
        </li>
    {% endfor %}
</ul>

Нотацией для тегов шаблона назначения является {% template_tag as variable %}. Для тега шаблона мы используем {% get_most_commented_posts as most_commented_posts %}. Таким образом, мы сохраняем результат тега шаблона в новой переменной с именем most_commented_posts. Затем отображаются возвращенные сообщения в виде неупорядоченного списка.

Теперь откройте браузер и обновите страницу, чтобы увидеть конечный результат. Он должен выглядеть следующим образом:

Вы можете узнать больше про создание пользовательских тегов шаблонизатора https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/

results matching ""

    No results matching ""