節約プログラマー雑記

puputでhtmlを直接記述

このサイトを作る際に、ブログ投稿のベースとしたpuputの投稿内容をhtmlで直接記述できるようにも修正しています。
やったこととしては、以下の2点。

  1. ブログ投稿モデル(abstracts.py)の修正
  2. テンプレート(blog_page.html, blog_entry.html)の修正


ブログ投稿モデル(abstracts.py)の修正


puputの公式ドキュメントを見るとブログの投稿ページを拡張する方法もあるようですが、そこまで大きな変更でもないため、今回は直接、本体ソースを修正します。pip show puputでpuputのソースの格納場所を確認し、配下のabstratcs.pyを開きます。修正は下記のような感じ。


ファイル名:abstracts.py
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel, PageChooserPanel,StreamFieldPanel #StreamFieldPanelを追加
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.core.fields import RichTextField, StreamField #StreamFieldを追加
from modelcluster.contrib.taggit import ClusterTaggableManager
from wagtail.core import blocks  #blocksをインポート
・・・(中略)・・・

#ブログ投稿クラスの修正 class EntryAbstract(models.Model): #既存のbody部分をコメントアウト #body = RichTextField(verbose_name=_('body')) #bodyをStreamFieldのRichTextBlockとRawHTMLBlockに変更 body = StreamField([ ('paragraph',blocks.RichTextBlock()), ('htmlcode',blocks.RawHTMLBlock()), ],verbose_name=_('body') #ここまで# ,null=True ,blank=True) tags = ClusterTaggableManager(through='puput.TagEntryPage', blank=True) date = models.DateTimeField(verbose_name=_("Post date"), default=datetime.datetime.today) ・・・(中略)・・・ content_panels = [ MultiFieldPanel( [ FieldPanel('title', classname="title"), ImageChooserPanel('header_image'), StreamFieldPanel('body', classname="full"),#bodyのパネルをStreamFieldPanelに変更 FieldPanel('excerpt', classname="full"), ], heading=_("Content") ), MultiFieldPanel( [ FieldPanel('tags'), InlinePanel('entry_categories', label=_("Categories")), InlinePanel( 'related_entrypage_from', label=_("Related Entries"), panels=[PageChooserPanel('entrypage_to')] ), ], heading=_("Metadata")), ]

puputの投稿部分は、もともとRichTextFieldになっているため、その箇所を複数の入力方法を可能とするStreamFieldに変更します。今回の場合、リッチテキスト形式の入力を残しつつ、生のHTMLを入力をできるようにしたかったため、StreamFieldの中身をRichTextBlock()とRawHTMLBlock()に設定しました。最後に、Wagtail側の投稿画面の入力フォームを合わせるために、content_panelsの"body"を部分をStreamFieldPanelに変更してモデルの修正が完了です。

ですが、このままだと、表示するテンプレート側がレンダリングの際にエラーになってしまうため、こちら側も修正が必要になります。


テンプレート(blog_page.html, blog_entry.html)の修正


テンプレート側のファイルもabstracts.pyと同様にpuputのソースを直接修正します。abstracts.pyが格納されているフォルダ内の、./templates/puputフォルダ内に、blog_page.html,entry_page.htmlがあり、これが投稿したブログに影響しますのでこれを修正します。

ファイル名:blog_page.html
・・・(省略)・・・
 <section class="article">
      {% if entry.excerpt %}
          {{ entry.excerpt|richtext }}
      {% else %}
          #修正ここから
           {#{{ entry.body|richtext|truncatewords_html:70 }}#}
          {% for block in entry.body %}
              {% if forloop.first %}
                  {{ block.value | richtext | truncatewords_html:70 }}
              {% endif %}
          {% endfor %}
           #修正ここまで
      {% endif %}

ファイル名:entry_page.html
・・・(省略)・・・
 <section>
     #修正ここから
     {#{{ self.body|richtext}}#}
     {% for block in self.body %}
         {% include_block block %}
     {% endfor%}
     #修正ここまで

どちらも、もともとリッチテキストだった部分が階層化されているため、テンプレートのfor文を活用して、順次出力していくような修正をしています。修正完了後、Wagtail(Django)のプロジェクトフォルダに移動して、python manage.py migrateを実行して、修正内容を反映して一通りの作業が完了になります。これで、管理画面側から、htmlを入力可能になり、入力したhtmlを画面にも出力できるようになりました!