В Django есть много разных встроенных фильтров, которые позволяют модифицировать переменные в шаблонах. Это функции Python, принимающие один или два параметра: значение переменной, к которой она будет применена и опциональный аргумент. Они возвращают значение, которое может быть отображено или стать еще одним фильтром. Фильтр выглядит следующим образом {{ variable|my_filter }}
. А фильтры с аргументом так — {{ variable|my_filter:"foo" }}
. К переменной можно применять сколько угодно фильтров, например, {{ variable|filter1|filter2 }}
. Каждый из них будет применен в выводу, который сгенерирует предыдущий.
Создадим собственный фильтр, который позволит использовать разметку Markdown в постах блога и затем конвертировать содержимое в код HTML в шаблонах. Markdown — это синтаксис для форматирования обычного текста, который затем превращается в HTML. С основами этого формата можно ознакомиться по ссылке https://daringfireball.net/project/markdown/basics.
Сперва установите модуль Markdown в Python с помощью pip
:
pip install Markdown==2.6.11
Затем отредактируйте файл blog_tags.py
и добавьте следующий код:
from django.utils.safestring import mark_safe
import markdown
@register.filter(name='markdown')
def markdown_format(text):
return mark_safe(markdown.markdown(text))
Фильтры шаблона регистрируются так же, как и шаблонные теги. Чтобы избежать конфликта имени функции с модулем markdown первую нужно назвать markdown_format
, а фильтр для шаблонов — markdown
: {{ variable|markdown }}
. Django исключает HTML-код, сгенерированный фильтрами. Функция mark_sage
из Django используется, чтобы отметить, какой HTML-код нужно отрендерить стандартным путем. По умолчанию, Django будет исключать любой HTML-код перед выводом. Единственные исключения — отмеченные переменные. Такое поведение предотвращает возможный вывод потенциально опасного кода и позволяет создавать исключения для возврата безопасного HTML-кода.
Теперь загрузите шаблонные теги в шаблоны со списком постов и страницей поста. Добавьте следующую строку в верхней части шаблонов blog/post/list.html
и blog/post/detail.html
после тега {% extends %}
:
{% load blog_tags %}
В шаблоне post/detail.html
взгляните на следующую строку:
{{ post.body|linebreaks }}
Замените ее на эту:
{{ post.body|markdown }}
Затем в файле post/list.html
замените эту строку:
{{ post.body|truncatewords:30|linebreaks }}
На эту:
{{ post.body|markdown|truncatewords_html:30 }}
Фильтр truncatewords_html
обрезает строку после определенного количества слов, избегая незакрытых HTML-тегов.
Теперь откройте https://127.0.0.1:8000/admin/blog/post/add в браузере и добавьте пост со следующим тегом.
This is a post formatted with markdown
--------------------------------------
*This is emphasized* and **this is more emphasized**.
Here is a list:
* One
* Two
* Three
And a [link to the Django website](https://www.djangoproject.com/)
Откройте браузер и посмотрите, как он отрендерился. Должно выглядеть вот так:
Как можно видеть на скриншоте, собственные фильтры шаблонов очень удобны для форматирования. Больше об этой теме здесь: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#writing-custom-template-filters.