Как отобразить Markdown в приложении Django

Оглавление

Одной из самых популярных функций Django является интерфейс администратора. Для разработчиков он предоставляет готовый набор инструментов для работы с моделями данных вашего проекта. И это дает администраторам-нетехникам интуитивно понятный пользовательский интерфейс (UI) для взаимодействия с базой данных и создания контента веб-сайта. Однако администратор Django не предоставляет возможности форматировать текстовый контент. Использование Markdown в Django - отличное решение.

Markdown - это язык форматирования обычного текста, который может автоматически преобразовываться в HTML для публикации в Интернете. Благодаря доступному синтаксису и широкому использованию в генераторах статических сайтов, приложениях для повышения производительности и инструментах управления контентом, он стал популярной альтернативой текстовым редакторам как для технических, так и для нетехнических создателей контента.

Есть также несколько сторонних Что Вы видите, то вы и получаете ( WYSIWYG) редакторы, доступные для Django. Они предоставляют интерфейс для форматирования текста с помощью кнопок в строке меню во время написания, аналогичный текстовому редактору. Другие варианты включают использование системы управления контентом, такой как Wagtail CMS, или работу непосредственно с файлами шаблонов HTML.

Но при использовании в сочетании с администратором Django, Markdown предоставляет более простую альтернативу полноценной CMS и более удобный пользовательский интерфейс, чем при работе с HTML-шаблонами, как для разработчиков, так и для авторов контента.

Многие авторы считают, что работать с Markdown быстрее и проще, чем с WYSIWYG-интерфейсом. Кроме того, разделение текстового и презентационного уровней вашего веб-контента дает дополнительные преимущества, включая повышенную безопасность, меньший риск синтаксических ошибок и возможность публикации в различных форматах, таких как электронная почта или PDF-документы.

В этом руководстве вы узнаете, как визуализировать содержимое Markdown с помощью Django, чтобы создатели контента вашего веб-сайта могли воспользоваться преимуществами простоты и удобства, которые сделали Markdown таким популярным выбором для форматирования текстового контента. В этом руководстве предполагается, что у вас уже есть некоторый опыт работы с Django, поэтому, если вы совершенно новичок в этом фреймворке, вы можете научиться создавать свое первое приложение на Django здесь.

Как использовать Markdown для содержимого в приложении Django

В приложении Django включение Markdown может улучшить рабочий процесс управления контентом для пользователей, которые предпочитают форматировать свои записи в виде обычного текста, а не в редакторе WYSIWYG. В этом разделе руководства вы узнаете, как расширить приложение Django, чтобы оно позволяло создавать содержимое Markdown, управлять им и отображать его.

Вы узнаете о настройке проекта и приложения Django, определении модели для хранения содержимого Markdown и создании шаблонов Django для отображения этого содержимого в формате HTML. Кроме того, вы изучите использование Python-Markdown для преобразования Markdown в HTML в ваших представлениях Django.

К концу этого раздела у вас будет полностью функциональная система управления контентом Markdown в вашем приложении Django.

Создайте приложение Django для отображения контента

Чтобы отобразить HTML-контент, записанный как Markdown, с помощью Django, начните с создания нового проекта Django с именем dmd_project внутри виртуальной среды Python . Вы используете dmd в качестве сокращения для Django Markdown:

(venv) PS> mkdir django-markdown
(venv) PS> django-admin startproject dmd_project django-markdown
(venv) $ mkdir django-markdown/
(venv) $ django-admin startproject dmd_project django-markdown/

Единственными зависимостями, которые вам понадобятся для этого руководства, являются Django и пакет Python-Markdown, который предоставляет API для работы с Markdown в Python. Установить markdown в вашу виртуальную среду с помощью pip:

(venv) PS> python -m pip install markdown
(venv) $ python -m pip install markdown

Теперь создайте новое приложение Django с помощью команды manage.py startapp:

(venv) PS> cd django-markdown
(venv) PS> python manage.py startapp dmd_app
(venv) $ cd django-markdown/
(venv) $ python manage.py startapp dmd_app

Вы использовали команду startapp для создания папки dmd_app/, которая содержит файлы, необходимые для создания этого содержимого через интерфейс администратора Django, сохранения его в базе данных вашего проекта и отображения пользователям в виде HTML. Добавьте ваше новое приложение в настройку INSTALLED_APPS в файле settings.py вашего проекта:

dmd_project/settings.py

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "dmd_app",
]

Чтобы создать новую таблицу базы данных для хранения содержимого вашего проекта, определите модель MarkdownContent в файле models.py в вашем каталоге dmd_app/:

dmd_app/models.py

from django.db import models

class MarkdownContent(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

    class Meta:
        verbose_name_plural = "Markdown content"

    def __str__(self):
        return self.title

Ваша модель MarkdownContent содержит два поля: поле title, ограниченное сотней символов, и поле content, которое может содержать неограниченное количество текста. Поле content - это поле, в котором вы будете хранить свой веб-контент в формате Markdown.

После определения вашей модели запустите команды управления makemigrations и migrate Django, которые преобразуют ваш код на Python в SQL и выполнят его в вашем проектебаза данных для создания таблицы:

(venv) PS> python manage.py makemigrations
(venv) PS> python manage.py migrate
(venv) $ python manage.py makemigrations
(venv) $ python manage.py migrate

Теперь, когда вы определили свою модель MarkdownContent, зарегистрируйте ее в модуле admin. Это позволяет создателям контента вашего веб-сайта входить в систему и создавать свой контент через интерфейс администратора:

dmd_app/admin.py

from django.contrib import admin
from .models import MarkdownContent

admin.site.register(MarkdownContent)

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

(venv) PS> python manage.py createsuperuser
(venv) $ python manage.py createsuperuser

Используйте команду runserver управления Django, чтобы запустить локальный сервер разработки, а затем перейдите к http://127.0.0.1:8000/admin/ в вашем браузере. Теперь вы должны увидеть экран входа в систему администратора, где вы можете ввести имя пользователя и пароль, которые вы только что создали. Войдите в систему, чтобы просмотреть интерфейс администратора с разделом для создания записей базы данных для вашей модели MarkdownContent:

Django admin screen Раздел интерфейса администратора Django для ваших моделей контента Markdown

Нажмите на ссылку Содержимое Markdown, а затем на кнопку с надписью ДОБАВИТЬ содержимое MARKDOWN в правом верхнем углу экрана:

Django Admin Add New Content Где добавить свой контент Markdown в Django admin

Введите название и некоторое содержимое в поля формы, чтобы создать новую запись MarkdownContent и выберите Сохранить, что перенаправит вас в список администраторов для вашей записи MarkdownContent модель:

Django Admin List View Просмотр списка администраторов Django для ваших экземпляров модели контента Markdown

Теперь, когда вы создали некоторый исходный контент, вы можете добавить последние фрагменты, необходимые вашему проекту Django для отображения этого контента для ваших пользователей:

  • HTML-файл шаблона
  • Функция просмотра на Python
  • Шаблон URL-адреса для вашей страницы

Начните с создания новой папки для хранения файлов шаблонов Django по адресу dmd_app/templates/. Затем создайте подпапку внутри templates/ с именем dmd_app/ и новым файлом внутри с именем markdown_content.html.

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

dmd_app/templates/dmd_app/markdown_content.html

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Django Markdown</title>
  </head>
  <body>
    <h1>{{ markdown_content.title }}</h1>
    <p>{{ markdown_content.content }}</p>
  </body>
</html>

Здесь вы создали HTML-шаблон, используя синтаксис переменной шаблона Django {{ markdown_content.title }}, который Django заменит на значения экземпляра вашей модели MarkdownContent при отображении страницы в браузере. Но сначала вам нужно загрузить экземпляр вашей модели из базы данных в ваш файл представления Django.

В файле views.py вашего каталога dmd_app/ определите функцию просмотра для извлечения записи MarkdownContent, которую вы только что создали как экземпляр модели, и передайте этот экземпляр в качестве контекстной переменной для рендеринга в вашем шаблоне:

dmd_app/views.py

from django.shortcuts import render
from .models import MarkdownContent

def markdown_content_view(request):
    markdown_content = MarkdownContent.objects.first()
    context = {"markdown_content": markdown_content}
    return render(
        request,
        "dmd_app/markdown_content.html",
        context=context
    )

Этот код использует .objects.first() для извлечения единственного экземпляра MarkdownContent, который вы создали в Django admin. Обратите внимание, что этот код просмотра завершится ошибкой, если вы еще не создали экземпляр модели MarkdownContent. Вы улучшите этот код позже в этом руководстве, но пока не забудьте создать свой начальный экземпляр модели в admin, выполнив описанные выше действия, прежде чем он будет запущен.

Добавьте новый объект path в список urlpatterns в файле urls.py вашего проекта, чтобы определить шаблон URL для вашей страницы содержимого:

dmd_project/urls.py

from django.contrib import admin
from django.urls import path
from dmd_app.views import markdown_content_view

urlpatterns = [
    path("admin/", admin.site.urls),
    path(
        "markdown-content/", markdown_content_view, name="markdown-content"
    ),
]

Объект path, который вы добавили в urlpatterns, содержит три параметра. У вас есть строка URL-адреса, функция просмотра markdown_content_view(), которую Django будет вызывать, когда пользователь перейдет по URL-адресу в своем браузере, и уникальное имя URL-адреса для использования в шаблонах Django.

Теперь, если вы перейдете к http://127.0.0.1:8000/markdown-content/ в вашем браузере, то вы должны увидеть содержимое, которое вы создали в админ-окне. Теперь, когда у вас есть все необходимые компоненты для создания, сохранения и отображения контента на вашем веб-сайте, вы можете добавить возможности рендеринга Markdown в свой проект Django.

Добавьте содержимое Markdown в ваше приложение Django

Снова войдите в систему администратора, выберите Содержимое Markdown, а затем нажмите на ссылку на содержимое Markdown с экземпляром вашей модели из списка под названием Выберите содержимое markdown, чтобы изменить. Замените текст, который вы ввели в поле Содержимое, новым текстом, включающим уценку:

### I'm a header

I'm a paragraph with some **bold** and *emphasized* text.

- I
- am
- a
- list

```
# I am some Python code

def do_stuff():
    pass
```

В этом тексте используется синтаксис Markdown для создания заголовка, абзаца, неупорядоченного списка и блока кода. После замены содержимого текстом, включающим Markdown, нажмите Сохранить:

Markdown Content Редактирование вашего контента в Django admin для использования Markdown

Вернитесь к http://127.0.0.1:8000/markdown-content/ в вашем браузере, и вы увидите огромный беспорядок:

Markdown With Syntax Symbols Текст с синтаксисом Markdown, отображаемый в браузере

Но вы можете исправить это, используя пакет Python-Markdown, который вы установили при первоначальной настройке вашего проекта. В свой файл dmd_app/views.py импортируйте модуль markdown и отредактируйте свой код, чтобы он выглядел следующим образом:

dmd_app/views.py

import markdown
from django.shortcuts import render
from .models import MarkdownContent

def markdown_content_view(request):
    md = markdown.Markdown(extensions=["fenced_code"])
    markdown_content = MarkdownContent.objects.first()
    markdown_content.content = md.convert(markdown_content.content)
    context = {"markdown_content": markdown_content}
    return render(
        request,
        "dmd_app/markdown_content.html",
        context=context
    )

Здесь вы инициализируете markdown.Markdown в своей функции просмотра, передавая параметр fenced_code в параметр extensions, который позволяет отображать отформатированные блоки кода. Затем вы вызываете .convert() для атрибута markdown_content экземпляра модели content, преобразуя ваш контент в HTML. Но теперь, если вы загрузите страницу по адресу http://127.0.0.1:8000/markdown-content/, то увидите фактическую HTML-разметку, отображаемую на экране:

HTML Displayed In Browser Текст с HTML-разметкой, отображаемый в браузере

Вы можете исправить это, добавив встроенный в Django safe фильтр к переменной markdown_content.content в вашем файле шаблона:

dmd_app/templates/dmd_app/markdown_content.html

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Django Markdown</title>
  </head>
  <body>
      <h1>{{ markdown_content.title }}</h1>
      <p>{{ markdown_content.content|safe }}</p>
  </body>
</html>

Этот встроенный фильтр шаблонов сообщает движку шаблонов Django, что динамическое содержимое поля content получено из надежного источника и безопасно преобразуется в HTML. Теперь ваш контент должен правильно отображаться для пользователей вашего веб-сайта:

Properly Rendered Markdown

Правильно отформатированный HTML-текст, отображаемый в браузере

Теперь у вас есть форматирование Markdown, работающее в Django admin. И, если вы хотите отформатировать контент на других страницах вашего веб-сайта, вы можете обратиться к более удобному для повторного использования решению, создав пользовательский фильтр шаблонов в следующем разделе.

Отформатируйте Markdown с помощью пользовательского фильтра шаблонов Django

Такой подход к форматированию Markdown работает как быстрое, одноразовое решение в приложении Django. Но он тесно связан с представлением и кодом модели для данного конкретного случая использования. А если вы захотите использовать Markdown в других областях своего веб—сайта, то в итоге получите много повторяющегося и избыточного кода, который утомительно поддерживать, а это никогда не бывает хорошо!

Было бы неплохо, если бы вы могли написать код форматирования один раз и добавить его в любое поле в своих шаблонах таким же образом, как вы добавили встроенный фильтр safe в предыдущем примере. Благодаря пользовательским тегам шаблонов и фильтрам в Django вы можете это сделать.

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

Чтобы задать пользовательский фильтр Markdown, начните с создания нового каталога templatetags/ внутри dmd_app/ рядом с views.py и другими стандартными файлами. Обязательно добавьте пустой __init__.py внутри templatetags/, чтобы Django мог распознать его как новый пакет Python. Затем создайте новый файл dmd_extras.py рядом с файлом __init__.py и добавьте следующий код:

dmd_app/templatetags/dmd_extras.py

import markdown

from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

register = template.Library()

@register.filter
@stringfilter
def render_markdown(value):
    md = markdown.Markdown(extensions=["fenced_code"])
    return mark_safe(md.convert(value))

В этом коде @register.filter регистрирует вашу функцию фильтрации render_markdown() с помощью тега вашего проекта и библиотеки фильтров, используя экземпляр template.Library с именем register. Параметр @stringfilter decorator указывает на то, что ваша функция будет принимать только строковые значения. Функция mark_safe() работает подобно встроенному фильтру safe, указывая, что HTML-символы из метода md.convert() безопасны для отображения без дальнейшего экранирования.

Обратите внимание, что в реальном проекте вам нужно будет продумать свой конкретный вариант использования, чтобы убедиться, что обрабатываемый вами текст действительно безопасен. Django предоставляет ряд гибких опций экранирования символов, которые можно использовать при определении пользовательских тегов и фильтров.

Теперь, когда вы переместили код рендеринга Markdown в свою пользовательскую функцию фильтрации, вы можете удалить код, связанный с Markdown, из своей функции просмотра:

dmd_app/views.py

from django.shortcuts import render
from .models import MarkdownContent

def markdown_content_view(request):
    markdown_content = MarkdownContent.objects.first()
    context = {"markdown_content": markdown_content}
    return render(
        request,
        "dmd_app/markdown_content.html",
        context=context
    )

Вместо этого вы можете использовать свой новый фильтр render_markdown() в коде шаблона:

dmd_app/templates/dmd_app/markdown_content.html

{% load dmd_extras %}

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Django Markdown</title>
  </head>
  <body>
    <h1>{{ markdown_content.title }}</h1>
    <p>{{ markdown_content.content|render_markdown }}</p>
  </body>
</html>

Теперь, если вы перезагрузите страницу по адресу http://127.0.0.1:8000/markdown-content/, то увидите, что ваш контент правильно отображен в формате HTML, как и раньше. Но теперь Django использует ваш пользовательский фильтр шаблонов, который вы также можете использовать в любом другом месте, где вы хотите разрешить редактирование на основе Markdown в администраторе вашего проекта.

Создайте свое собственное расширение для Python-Markdown

Хотя пакет Python-Markdown предоставляет все необходимые функциональные возможности для начала работы с текстом в формате Markdown в Python, он также дает вам возможность определять свои собственные пользовательские расширения. Это позволяет вам настроить синтаксис Markdown для дальнейшей оптимизации его интеграции с Django.

Чтобы проверить это, вы создадите расширение, которое может ссылаться на страницы веб-сайта с помощью слизней, а не URL-адресов, используя стандартный синтаксис встроенных ссылок Markdown из [link text](url). В веб-разработке термин slug относится к компоненту URL-адреса, состоящему из букв, цифр, знаков подчеркивания или дефисов и часто являющемуся производным от названия веб-страницы или раздела веб-сайта.

Ваш пользовательский синтаксис позволит авторам писать [link text](slug:page-slug), где page-slug - это значение поля slug, определенное в модели страницы. Это значительно улучшит пользовательский опыт создателей контента, избавив их от необходимости вводить полный URL-адрес для каждой внутренней страницы, на которую они хотят перейти по ссылке.

Django предоставляет SlugField поле модели, которое вы можете добавить в свое MarkdownContent определение модели, а затем применить к базе данных вашего проекта, выполнив команду python manage.py makemigrations, за которым следует python manage.py migrate в вашей консоли:

dmd_app/models.py

from django.db import models

class MarkdownContent(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    slug = models.SlugField(blank=True)

    class Meta:
        verbose_name_plural = "Markdown content"

    def __str__(self):
        return self.title

После выполнения команд переноса отредактируйте dmd_app/admin.py, чтобы создать значение для вашего поля MarkdownContent.slug на основе значения вашего поля title, когда вы вводите это значение в форму администратора для вашего модель выглядит так:

dmd_app/admin.py

from django.contrib import admin
from .models import MarkdownContent

class MarkdownContentAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ["title"]}

admin.site.register(MarkdownContent, MarkdownContentAdmin)

Теперь, если вы вернетесь к администратору, чтобы отредактировать содержимое своей страницы MarkdownContent, вы увидите, что новое поле заполняется при выборе поля формы для ваше поле Заголовок:

Django Admin Field With Slug Интерфейс администратора содержимого Markdown с новым полем slug

Выберите Сохраните, а затем отредактируйте файл вашего проекта urls.py, чтобы использовать поле MarkdownContent.slug в URL страницы:

dmd_project/urls.py

from django.contrib import admin
from django.urls import path
from dmd_app.views import markdown_content_view

urlpatterns = [
    path("admin/", admin.site.urls),
    path(
        "markdown-content/<slug:slug>/",
        markdown_content_view,
        name="markdown-content",
    ),
]

В этом коде вы обновили свой объект path, чтобы использовать новый параметр slug в строке URL. Теперь, если вы укажете в своем браузере на http://127.0.0.1:8000/markdown-content/my-first-markdown-content/, то Django примет значение slug, равное my-first-markdown-content, и передаст его в качестве параметра в markdown_content_view().

Но сначала вам нужно изменить свой код просмотра, чтобы он принимал page slug в качестве параметра, и использовать функцию Django get_object_or_404() для запроса страницы или возврата сообщения об ошибке, если slug в URL-адресе не существует:

dmd_app/views.py

from django.shortcuts import render, get_object_or_404
from .models import MarkdownContent

def markdown_content_view(request, slug):
    markdown_content = get_object_or_404(MarkdownContent, slug=slug)
    context = {"markdown_content": markdown_content}
    return render(
        request,
        "dmd_app/markdown_content.html",
        context=context
    )

Теперь, чтобы перейти на одну из ваших страниц MarkdownContent в вашем браузере, вам нужно добавить ссылку на конкретную страницу в конец URL-адреса, вот так: http://127.0.0.1:8000/markdown-content/my-first-markdown-content/.

Теперь вы можете создать пользовательское расширение для Markdown на Python, которое позволяет авторам контента использовать ваше новое поле slug как более лаконичный способ ссылки на внутренние URL-адреса веб-сайтов в своем контенте Markdown. Начните с создания нового файла в вашем каталоге dmd_app/ с именем markdown_extensions.py. Затем добавьте в этот файл следующий код:

dmd_app/markdown_extensions.py

import markdown
from django.urls import reverse
from markdown.inlinepatterns import LinkInlineProcessor, LINK_RE

class SlugFieldLinkInlineProcessor(LinkInlineProcessor):
    def getLink(self, data, index):
        href, title, index, handled = super().getLink(data, index)
        if href.startswith("slug"):
            slug = href.split(":")[1]
            relative_url = reverse("markdown-content", args=[slug])
            href = relative_url
        return href, title, index, handled

class SlugFieldExtension(markdown.Extension):
    def extendMarkdown(self, md, *args, **kwargs):
        md.inlinePatterns.register(
            SlugFieldLinkInlineProcessor(LINK_RE, md), "link", 160
        )

Здесь SlugFieldLinkInlineProcessor наследуется от LinkInlineProcessor, который отвечает за обработку встроенных ссылок, записанных в синтаксическом шаблоне Markdown [link text](url). Чтобы использовать тот же синтаксический шаблон для ссылок на страницы с их slugs, вы переопределяете .getLink() в своем подклассе и проверяете наличие встроенных ссылок, которые используют ваш пользовательский шаблон [link text](slug:page-slug).

Если встроенная ссылка начинается с "slug,", то вы используете .reverse() для создания полного относительного URL-адреса и возвращаете его как значение href. Затем вы создаете подкласс markdown.Extension, чтобы заменить LinkInlineProcessor своим пользовательским расширением.

Процессоры Markdown на Python запускаются в определенном порядке, чтобы правильно преобразовать синтаксис Markdown в HTML-код. Сначала они должны обрабатывать обратные кавычки и экранированные символы, затем ссылки, а затем встроенный HTML. Поскольку ваше расширение добавляет функциональность к существующему процессору LinkInlineProcessor, вы хотите использовать тот же уровень приоритета 160, что и у исходного базового класса.

При создании собственных пользовательских расширений вы можете ознакомиться с порядком обработки по умолчанию в Python-Markdown, просмотрев исходный код . Кроме того, вы можете узнать больше о реализации пользовательских расширений Python-Markdown в их официальном руководстве .

Следующим шагом будет добавление вашего пользовательского SlugFieldExtension в список расширений Python-Markdown, где вы создаете экземпляр класса markdown.Markdown в вашем фильтре пользовательских шаблонов dmd_extras.render_markdown():

dmd_app/templatetags/dmd_extras.py

import markdown

from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

from dmd_app.markdown_extensions import SlugFieldExtension

register = template.Library()

@register.filter
@stringfilter
def render_markdown(value):
    md = markdown.Markdown(extensions=["fenced_code", SlugFieldExtension()])
    return mark_safe(md.convert(value))

Теперь снова войдите в систему администратора и создайте новую запись на странице Содержание Markdown:

Django Admin New Content

Создание нового экземпляра содержимого Markdown в Django admin

Затем отредактируйте поле Содержимое вашей исходной страницы Содержимое Markdown, чтобы использовать пользовательский синтаксис Markdown поля slug, [link text](slug:page-slug), где page-slug - это значение поля slug для новой страницы Markdown content, которую вы только что создали:

Django Markdown Custom Slug Syntax

Редактирование исходного содержимого Markdown для использования пользовательского встроенного синтаксиса slug

Сохраните изменения и перейдите на страницу исходного контента, где вы должны увидеть свой новый контент, отображаемый в виде встроенной привязочной ссылки в формате HTML:

Page With Slug Link

Визуализированный HTML-текст с использованием пользовательского синтаксиса slug для создания привязочной ссылки

Нажмите на ссылку, и ваш браузер перейдет на вашу новую страницу Markdown content, используя относительное значение URL, полученное вашим пользовательским расширением Markdown на Python из page slug:

New Content Page

Рабочая анкорная ссылка на вашу вторую страницу контента Markdown

Благодаря возможности подключаться к коду Markdown на Python на любом этапе процесса рендеринга, существует бесчисленное множество способов расширить его функциональные возможности по умолчанию и настроить свои собственные интеграции Markdown для работы с Django. В этом небольшом примере вы изменили синтаксис встроенных ссылок Markdown для работы с полем slug в Django и django.urls.reverse(), так что теперь у вас есть представление о потенциальных преимуществах сочетания этих двух технологий.

Добавьте подсветку синтаксиса кода к содержимому Markdown

Иметь возможность писать свои собственные расширения для Python Markdown - это здорово, но, как и во всем, что касается разработки программного обеспечения, лучше не изобретать велосипед, когда есть готовое решение, отвечающее вашим потребностям.

Добавление подсветки синтаксиса к блокам кода в вашем контенте Markdown было бы хорошей возможностью улучшить читаемость для пользователей вашего веб-сайта. Но это было бы сложной задачей для реализации в виде пользовательского расширения. К счастью, Python-Markdown предоставляет официально поддерживаемое расширение CodeHilite, которое вы можете подключить к своему проекту и использовать бесплатно.

Чтобы использовать расширение CodeHilite, вы должны сначала установить Pygments, пакет подсветки синтаксиса кода для Python:

(venv) PS> python -m pip install Pygments
(venv) $ python -m pip install Pygments

Установив Pygments, вы можете использовать его pygmentize утилиту командной строки для создания таблицы стилей CSS, чтобы добавить подсветку синтаксиса к вашим блокам кода.

Но сначала вам нужно создать новую папку static/ внутри dmd_app/, чтобы Django знал, где найти ваш статический CSS-файл. Внутри этой папки static/ создайте еще одну новую папку с именем dmd_app/, которая распределяет эти файлы по именам так же, как вы это делали ранее со структурой папок вашего шаблона.

Измените каталоги на новую папку со статическими файлами и выполните следующую команду pygmentize:

(venv) PS> cd dmd_app/static/dmd_app
(venv) PS> pygmentize -S default -f html -a .codehilite > styles.css
(venv) $ cd dmd_app/static/dmd_app
(venv) $ pygmentize -S default -f html -a .codehilite > styles.css

Эта команда указывает Pygments создать новый styles.css файл со стилями CSS, чтобы добавить подсветку синтаксиса в HTML-код вашего проекта, используя настройки цвета по умолчанию в Pygments и .codehilite имя класса CSS. Расширение CodeHilite затем добавит .codehilite Имя класса CSS в ваши блоки кода, когда Python-Markdown отрисует ваш HTML из Markdown.

Чтобы использовать файл styles.css в вашем HTML-коде, вам необходимо внести следующие изменения в код вашего шаблона:

dmd_app/templates/dmd_app/markdown_content.html

{% load static %}
{% load dmd_extras %}

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Django Markdown</title>
    <link rel="stylesheet" type="text/css"
          href="{% static 'dmd_app/styles.css' %}">
  </head>
  <body>
    <h1>{{ markdown_content.title }}</h1>
    <p>{{ markdown_content.content|render_markdown }}</p>
  </body>
</html>

Этот код использует тег шаблона Django static, который указывает на ваш файл styles.css, чтобы вы могли загрузить его с помощью элемента HTML <link>.

Перейдите к интерфейсу администратора Django в вашем браузере и вернитесь к первому экземпляру Содержимого Markdown, который вы создали. Обновите блок кода, который вы ввели в поле Содержимое, чтобы он выглядел следующим образом:

```python
# I am some Python code

def do_stuff():
    pass
```

Добавление python в блок кода Markdown указывает CodeHilite, какой язык программирования использовать для подсветки синтаксиса. Вы можете проверить это, добавив еще один блок кода в ваше поле Содержимое с выделенным HTML-кодом:

```html
<!-- I am some HTML code -->

<h1>My Cool Headline</h1>
```

Сохраните изменения и откройте dmd_extras.py, где вы определили свой пользовательский фильтр шаблона render_markdown(). Обновите render_markdown(), чтобы использовать расширение CodeHilite:

dmd_app/templatetags/dmd_extras.py

# ...

@register.filter
@stringfilter
def render_markdown(value):
    md = markdown.Markdown(
        extensions=["fenced_code", "codehilite", SlugFieldExtension()]
    )
    return mark_safe(md.convert(value))

Поскольку CodeHilite является одним из официально поддерживаемых расширений Python-Markdown , все, что вам нужно сделать, это добавить строку "codehilite" в свой список extensions аргументируйте, и это просто сработает.

Просмотрите исходную страницу содержимого Markdown в вашем браузере еще раз, и вы увидите, что подсветка синтаксиса работает должным образом для ваших блоков кода Python и HTML:

Code Blocks With Syntax Highlighting

Блоки кода с подсветкой синтаксиса

Теперь ваш HTML-контент включает подсветку синтаксиса, которая является приятной функцией для удобства чтения пользователями вашего веб-сайта. В дополнение к официально поддерживаемым расширениям Python-Markdown, также доступно множество сторонних расширений.

Заключение

В этом руководстве вы узнали, как использовать пакет Markdown на Python для отображения содержимого Markdown в приложении Django. Этот пакет предоставляет возможность создавать содержимое веб-сайта с использованием синтаксиса Markdown в Django admin.

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

Вы раскрыли потенциал пользовательских расширений Markdown на Python, создав расширение, которое использует встроенный синтаксис ссылок Markdown для преобразования фрагментов веб-страниц в URL-адреса. И вы начали изучать экосистему официальных и сторонних расширений Markdown, используя расширение CodeHilite для добавления подсветки синтаксиса к блокам кода в контенте вашего веб-сайта.


Вернуться на верх