Wagtail管理画面でVS Code風HTML編集を実現する
wagtail 13 min read

Wagtail管理画面でVS Code風HTML編集を実現する

avatar-m-1

karrinn

著者

WordPressでブログやサイトを運用しては放置、を10年で5、6回繰り返してきました。ライターではなくソフトウェアエンジニアの私にとって、プラグイン探しやテーマのルールを覚えることは本業とは別の作業で、次第に億劫になっていったのです。
そんなとき出会ったのが、Pythonエンジニアにぴったりのヘッドレスに近いフルスタックCMS「Wagtail」でした。そして、Wagtailでの開発体験をさらに良くするために作ったのが、今回紹介する「wagtail-html-editor」です。

KEY TAKEAWAYS

この記事でわかること

  • Wagtail CMSとは何か、WordPressとの違い
  • wagtail-html-editorが解決する課題と主要機能
  • インストールから実際の使い方まで

前置き: Wagtailとは

Wagtailは日本ではそこまでシェアの高いCMSではないので、読者の方の中にはWagtailユーザでない方もいらっしゃると思います。本題に入る前に、簡単に前提知識を共有させてください。

WagtailはPython/Djangoベースのオープンソース製CMS。NASA、Google、英国NHSなど大規模組織での採用実績があります。WordPressと違い、プラグインを探して組み合わせるのではなく、Djangoの知識でコードを書いて機能を実装するスタイルです。

「プログラマーにとって最良のUIは、プログラミング言語そのもの」という設計思想(The Zen of Wagtail)のもと、コア機能は最小限に保ち、必要な機能はパッケージとして追加する軽量設計を採用しています。私がWordPressを何度立ち上げても続かなかったのに、Wagtailでは快適に運用できているのは、まさにこの「エンジニアがコードで自由に作れる」体験があるからです。今お読みいただいているこの記事自体も、今回紹介するwagtail-html-editorとwagtail-reusable-blocksを使って執筆しています。こういうことがガンガンできるのも、Wagtailを気に入っている理由の一つです。

参考: The Zen of Wagtail

なぜwagtail-html-editorを作ったのか

Wagtailは素晴らしいCMSですが、使い込むうちに一つの課題が見えてきました。

課題: ブロック定義の爆発

企業HP、ポートフォリオ、ブログ、案件先の開発と複数のWagtailサイトを運用する中で、レイアウトが少し違うだけ、編集可能箇所を少し増やすだけでブロック定義やフィールドが爆発的に増えていくことに気づきました。

  • 2カラムレイアウトのブロック
  • 3カラムレイアウトのブロック
  • 画像左寄せのブロック...

解決策: HTMLでレイアウトを書く

ブロックは機能を持った部分(画像、リッチテキストなど)に絞り、レイアウトはHTMLブロックで表現する。これがWagtailを選ぶ私のようなエンジニアにとって自然なアプローチだと気づきました。

  • ブロック数の爆発が消滅
  • 管理エクスペリエンスが向上
  • レイアウトの自由度が最大化

しかし、WagtailデフォルトのRawHTMLBlockはただのtextarea。しばらくの間、VS Codeでコーディングしてプレビュー確認し、管理画面にコピペするという運用をしていました。ブロック爆発問題は解決しましたが、「管理画面でもHTMLを快適に編集できれば文句なしだ」と気づき、開発に至りました。

設計思想: 専用知識ゼロで使えること

ライブラリを作るにあたって、いくつか心がけたことがあります。

リポジトリをクリーンに保ちたい

「エンジニアにとって最高のインターフェースはプログラミング言語」というWagtailの思想には共感しています。でも、ちょっとだけ違うブロックを実装しまくってリポジトリが汚れていくのは嫌。レイアウトはHTMLブロックに任せて、コードベースはスッキリ保ちたかったのです。

ライブラリ専用知識はゼロに

DjangoやPandasのような知名度のあるライブラリなら、専用ルールを覚えるのも苦になりません。でも今回のようなライブラリで「ここにこう書かないと動きません」は困る。INSTALLED_APPSに追加するだけで、いい感じのデフォルト設定ですぐ使い始められることを最優先にしました。

応用的な設定やカスタマイズは、ハマってくれた人のために用意してあります。でもまずは「入れたら動く」。これがサードパーティライブラリとして最低限守るべきラインだと考えています。

RawHTMLBlock vs EnhancedHTMLBlock

実際にどれだけ編集体験が変わるか、見てみましょう。

Before: RawHTMLBlock

Wagtail標準のRawHTMLBlockは、意図的にシンプルなtextareaとして設計されています。 シンタックスハイライトなし、インデント補助なし。複雑なHTMLを書くには厳しい環境でした。

rowhtmlblock-demo
demo.gif

After: EnhancedHTMLBlock

wagtail-html-editorを使うと、VS Code風の編集体験がWagtail管理画面で実現します。 シンタックスハイライト、Emmet対応、自動インデント、フルスクリーンモードなど、コーディングに必要な機能が揃っています。

wagtail-html-editorの主要機能

CodeMirror 6をベースに、Wagtail管理画面に最適化された機能を提供します。

機能説明対応
シンタックスハイライトHTML、CSS、JavaScriptを色分け表示
自動インデントVS Codeライクなスマートインデント
Emmetサポートdiv.container>ul>li*3 をTabで展開
ダーク/ライトモードWagtail管理画面のテーマに自動追従
フルスクリーンモード左パネル全体に拡大、ESCで終了
HTMLオートコンプリートタグ名、属性の補完入力
自動閉じタグ開始タグ入力時に終了タグを自動挿入

参考: wagtail-html-editor GitHub

インストールと使い方

既存のWagtailプロジェクトへの導入は非常にシンプルです。

1. パッケージをインストール

pipでインストールするだけ。依存関係はWagtail 6.0以上、Django 4.2以上です。

terminal
pip install wagtail-html-editor

2. INSTALLED_APPSに追加

settings.pyのINSTALLED_APPSにアプリを追加します。

settings.py
INSTALLED_APPS = [
    # ...
    'wagtail_html_editor',
    # ...
]

3. ページモデルで使用

RawHTMLBlockの代わりにEnhancedHTMLBlockをインポートして使うだけ。既存データとの互換性もあります。

  • EnhancedHTMLBlock: 強化版HTMLブロック
  • ブロック名を同じにすれば移行不要
models.py
from wagtail.models import Page
from wagtail.fields import StreamField
from wagtail.admin.panels import FieldPanel
from wagtail_html_editor.blocks import EnhancedHTMLBlock

class ContentPage(Page):
    body = StreamField([
        ('html', EnhancedHTMLBlock()),
        # ... other blocks
    ], blank=True, use_json_field=True)

    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]

参考: wagtail-html-editor README

RawHTMLBlockからの移行

すでにRawHTMLBlockを使っている場合、インポート文とブロッククラスを変更するだけで移行できます。ブロック名(例: 'html')を同じにしておけば、データベースマイグレーションは不要です。既存コンテンツはそのまま動作します。

技術スタック

Pythonライブラリを作りたい方向けに、採用した技術を紹介します。

CodeMirror 6を選んだ理由

エディタ基盤としてCodeMirror 6を採用しました。Ace EditorやMonacoも候補でしたが、以下の理由で決定しました。

  • モバイル対応: CodeMirror 6はモバイルブラウザでの動作が優秀(Replitの調査ではモバイルユーザーのリテンションが70%向上)
  • モジュラー設計: 必要な機能だけをインポートでき、バンドルサイズを最小化(Monacoは5-10MB、CodeMirrorは300KB程度から)
  • 後発のモダン設計: 2022年にリリースされた最新アーキテクチャ
  • 差別化: Ace Editorを使ったwagtail-ace-editorは既に存在していた
パッケージバージョン用途
codemirror^6.0.0コアエディタ
@codemirror/lang-html^6.4.0HTML言語サポート
@emmetio/codemirror6-plugin^0.3.0Emmet展開
vite^6.0.0ビルドツール

対応バージョン

幅広いバージョンをサポートするため、CI/CDで複数環境をテストしています。

  • Python: 3.10, 3.11, 3.12, 3.13, 3.14
  • Django: 4.2, 5.1, 5.2
  • Wagtail: 6.4, 7.0, 7.2

開発・品質管理ツール

OSSとして公開するにあたり、品質管理ツールを充実させました。

  • ビルド: hatchling + hatch-vcs(pyproject.toml準拠)
  • テスト: pytest, pytest-django, pytest-cov
  • 型チェック: mypy + django-stubs
  • リンター: ruff(Python), Biome(TypeScript)
  • マトリクステスト: tox + tox-uv
  • CI/CD: GitHub Actions

参考: CodeMirror公式, Replit: Comparing Code Editors

OSSとして公開して変わったこと

プライベートリポジトリでの開発時代は、セキュリティやプロジェクト管理への意識が低くなりがちでした。PyPIへの公開を始めてから、pyproject.tomlの設計、テスト、ドキュメントに至るまで「外部の人が理解・貢献できる」とはどういうことかを考えるようになりました。バージョンサポートの重要性やベストプラクティスへの意識が何段も上がったと感じています。

wagtail-reusable-blocksとの関係

wagtail-html-editorは単体でも使えますが、もう一つのライブラリと組み合わせるとさらに強力です。

LIBRARY

wagtail-reusable-blocks

HTMLでレイアウトを定義し、data-slot属性で動的コンテンツを挿入できる「スロットシステム」を提供するライブラリ。一度作ったレイアウトを複数ページで再利用できます。

INTEGRATION

オプション統合

pip install wagtail-reusable-blocks[editor]でインストールすると、wagtail-html-editorが自動的に有効になります。Wagtailの軽量思想に基づき、別パッケージとして切り出しています。

オプションでインストール

wagtail-reusable-blocksのextrasとして統合されているため、1コマンドで両方導入できます。

terminal
# 両方まとめてインストール
pip install wagtail-reusable-blocks[editor]

参考: wagtail-reusable-blocks GitHub

もっと詳しく知りたい方へ

関連トピック

コメント (0)

まだコメントはありません。最初のコメントを残しませんか?

コメントを投稿

メールアドレスが公開されることはありません。必須項目には * が付いています