Создание шаблонного фильтра для поддержки синтаксиса Markdown
Мы создадим конкретно-прикладной фильтр, который позволит использовать синтаксис упрощенной разметки Markdown в постах блога, а затем в шаблонах конвертировать текст поста в HTML.
Markdown – это синтаксис форматирования обычного текста, который очень прост в использовании и предназначен для конвертирования в HTML. Посты можно писать, используя простой синтаксис Markdown, и получать автоматическую конвертацию контента в исходный код HTML. Изучить синтаксис Markdown намного проще, чем изучить HTML. Используя Markdown, можно сделать так, чтобы другие не сведущие в технологиях участники легко писали посты для вашего блога.
С основами формата Markdown можно ознакомиться на странице https://daringfireball.net/projects/markdown/basics.
Сначала установите модуль Python markdown посредством pip, используя следующую ниже команду в командной оболочке:
pip install markdown
Затем отредактируйте файл templatetags/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; символы HTML-сущностей заменяются их кодированными в HTML символами. Например, <p> преобразовывается в <p>(символ <, символ p, символ >).
Мы используем предоставляемую веб-фреймворком Django функцию mark_safe, чтобы помечать результат как безопасный для прорисовки в шаблоне исходный код HTML. По умолчанию Django не будет доверять никакому исходному коду HTML и будет экранировать его перед его вставкой в результат.
Единственными исключениями являются переменные, которые помечены как безопасные, чтобы тем самым избежать экранирования. Такое поведение не дает Django выводить потенциально опасный исходный код HTML и позволяет создавать исключения, дабы возвращать безопасный исходный код HTML.
Отредактируйте шаблон blog/post/detail.html, добавив следующий ниже новый исходный код:
{% extends "blog/base.html" %}
{% load blog_tags %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|markdown }}
<p>
<a href="{% url 'blog:post_share' post.id %}">
Share this post
</a>
</p>
<h2>Similar posts</h2>
{% for post in similar_posts %}
<p>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</p>
{% empty %}
There are no similar posts yet.
{% endfor %}
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} comment{{ total_comments|pluralize }}
</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">
Comment {{ forloop.counter }} by {{ comment.name }}
{{ comment.created }}
</p>
{{ comment.body|linebreaks }}
</div>
{% empty %}
<p>There are no comments.</p>
{% endfor %}
{% include "blog/post/includes/comment_form.html" %}
{% endblock %}
Фильтр linebreaks шаблонной переменной {{ post.body }} был заменен фильтром markdown.
Данный фильтр не только преобразовывает разрывы строк в теги <p>, но и конвертирует форматирование Markdown в HTML.
Отредактируйте шаблон blog/post/list.html, добавив следующий ниже новый исходный код:
{% extends "blog/base.html" %}
{% load blog_tags %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% if tag %}
<h2>Posts tagged with "{{ tag.name }}"</h2> {% endif %}
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="tags">
Tags:
{% for tag in post.tags.all %}
<a href="{% url 'blog:post_list_by_tag' tag.slug %}">
{{ tag.name }}
</a>
{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|markdown|truncatewords_html:30 }}
{% endfor %}
{% include "pagination.html" with page=posts %}
{% endblock %}
В шаблонную переменную {{ post.body }} был добавлен новый фильтр markdown.
Этот фильтр преобразовывает контент в формате Markdown в формат HTML. Поэтому мы заменили приведенный выше фильтр truncatewords фильтром truncatewords_html. Данный фильтр усекает строку после определенного числа слов, избегая незакрытых HTML-тегов.
Теперь пройдите по URL-адресу http://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/) |
Форма должна выглядеть следующим образом:
Пройдите по URL-адресу http://127.0.0.1:8000/blog/ в своем браузере и посмотрите, как прорисовывается новый пост.
Вы должны увидеть следующий ниже результат:
На изображении хорошо видно, что конкретно-прикладные шаблонные фильтры очень удобны для адаптации форматирования под конкретно-прикладную задачу.
Более подробная информация о конкретно-прикладных фильтрах находится по адресу https://docs.djangoproject.com/en/5.0/howto/custom-template-tags/#writing-custom-template-filters.