Python DjangoとMDBで作る株取引ノート ⑦メモのマークダウン対応

Python DjangoとMDBで作る株取引ノートシリーズの7つ目の記事です。

今回は取引ノートのメモ部分をリッチエディタ、マークダウン投稿に対応させていきましょう。

使用ライブラリのインストール

requirements.txtに以下を追記しましょう。

django~=3.2.1
# 追加
django-mdeditor~=0.1.18
Markdown~=3.3.6


django-mdeditorは簡単にリッチエディタを表示できるライブラリです。
https://github.com/pylixm/django-mdeditor
markdownはエディタで入力したマークダウン記法で入力したテキストをhtmlに変換する際に使用します。

仮想環境をアクティベートしたのちにinstall しておきましょう

pip install -r requirements.txt


使用方法

まずsettings.pyに追記をします。

# project/settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'note.apps.NoteConfig',
    'django.contrib.humanize',
    'mdeditor',  # 追加,
]
...

MEDIA_URL = '/media/'  # 追加
MEDIA_ROOT = BASE_DIR / 'media'  # 追加

...

X_FRAME_OPTIONS = 'SAMEORIGIN'

MDEDITOR_CONFIGS = {
    'default': {
        'height': 300,
        'language': 'en',
        'lineWrapping': True
    }
}

# マークダウンの拡張
# 追加する場合は公式を参照
# https://python-markdown.github.io/extensions/
MARKDOWN_EXTENSIONS = [
    'markdown.extensions.extra',
    'markdown.extensions.nl2br',
]


次にproject内のurls.pyを以下のようにします。

# project/urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url  # 追加
from django.conf.urls.static import static  # 追加
from django.conf import settings  # 追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('note.urls')),
    url(r'mdeditor/', include('mdeditor.urls')),  # 追加
]

# 追加
# static files (images, css, javascript, etc.)
urlpatterns += static(settings.MEDIA_URL,
                      document_root=settings.MEDIA_ROOT)


次にモデルの該当箇所、memoにdjango-mdeditorのフィールドを適用させます。

# note/models.py

from django.db import models
from mdeditor.fields import MDTextField  # 追加

...

class Transaction(models.Model):
    """取引モデル"""
    ...
    # 変更
    memo = MDTextField(verbose_name='メモ', default='', null=True, blank=True)
    ...


変更したらmigrateしましょう。

python manage.py makemigrations
>>>
Migrations for 'note':
  note\migrations\0002_alter_transaction_memo.py
    - Alter field memo on transaction

python manage.py migrate
>>>
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, note, sessions
Running migrations:
  Applying note.0002_alter_transaction_memo... OK


成功したらアプリ内の編集画面を立ち上げてみてください。
このようにメモ部分がリッチなエディタになっていたらオッケーです。


本文の表示

次に本文、htmlの表示部分を対応させていきましょう。
例えば#見出しと入力したら<h1>見出し</h1>と出力させる、ということです。

これは最初にinstallしたmarkdownの機能を使ってフィルタを作成すると簡単です。
templatetags内のnote.pyに追記をします。

# note/templatetags/note.py

from django import template
# 追加
from django.conf import settings
from django.utils.safestring import mark_safe
import markdown

register = template.Library()

...

# 追加
@register.filter
def markdown_to_html(text):
    """マークダウンをhtmlに変換する。"""
    html = markdown.markdown(text, extensions=settings.MARKDOWN_EXTENSIONS)
    return mark_safe(html)


次にテンプレートのメモ表示部分を以下のようにします。

<!-- note/templates/note/detail.html -->
{% extends "note/base.html" %}
<!-- 追加 -->
{% load note %}

{% block content %}
<h1 class="mt-2">
  <a href="{% url 'note:transaction_update' transaction.pk %}">
    {{ transaction.ticker_code }} {{ transaction.ticker_name }}
  </a>
</h1>
<h4 class="mt-4">Reason</h4>
<p class="mt-2">{{ transaction.reason|linebreaks }}</p>
<h4 class="mt-4">Memo</h4>
<hr>
<!-- 変更 -->
<div class="markdown-text">  
  {{ transaction.memo|markdown_to_html }}
</div>
<hr>
...


style.cssにmarkdown表示用のstyleを追記しておきます。

/* note/static/note/css/style.css */

/* マークダウン関連 */
.markdown-text * {
  margin-top: 0;
  margin-bottom: 1em;
  line-height: 2.0;
  font-size: 1rem;
  font-weight: 500;
}

.markdown-text p {
  line-height: 2.0;
}

.markdown-text strong {
  background-color: yellow;
}

.markdown-text img {
  display: block;
  max-width: 100%;
  margin-top: 20px;
  margin-bottom: 20px;
  height: auto;
  border: solid 1px #ccc;
}

.markdown-text p code {
  background-color: #eee;
  color: #333;
  padding: 0.2em 0.4em;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  margin-left: 0.5rem;
  margin-right: 0.5rem;
}

.markdown-text pre {
  line-height: 1.2;
  background-color: #1D1F21;
  padding: 2% 4%;
  overflow-x: scroll;
}

.markdown-text pre * {
  margin-bottom: 0;
}

.markdown-text blockquote {
  padding: 10px 15px;
  border-left: 5px solid #ccc;
  border-radius: 2px;
  margin-top: 15px;
  margin-bottom: 15px;
}

.markdown-text h1 {
  font-size: 24px;
  font-weight: bold;
  margin-top: 20px;
  margin-bottom: 10px;
}

.markdown-text h2,
.markdown-text h3 {
  font-size: 20px;
  margin-top: 30px;
  margin-bottom: 10px;
  font-weight: bold;
}

.markdown-text .cp_embed_wrapper {
  margin-top: 20px;
  margin-bottom: 20px;
}

.markdown-text ul, .markdown-text ol {
  padding-left: 1.5em;
  margin: 1.5em 0;
  line-height: 1.9;
}

.markdown-text ul {
  list-style-type: disc;
}

.markdown-text ol {
  list-style-type: decimal;
}


試しに何か書いてみましょう
こういう感じで画像を交えて記載をしますと



表示は以下のようになります。




次回は簡単なダッシュボードページを作成していきます。

TOPページ