はじめに

Djangoでブログ機能を実装し、CKEditor4を使って記事を作成していますが、
見出しに付けたid属性が保存後に消えてしまう問題に遭遇しました。

例えば目次のアンカーリンクを作るために以下のように書いても、

<h3 id="section1">見出し</h3>

再度編集画面で開くと、

<h3>見出し</h3>

のように id属性だけが消えてしまう 状態になります。


目次


1. 発生した問題

CKEditorを使って記事を作成し、目次用のアンカーリンクを実装していました。

<a href="#section1">目次リンク</a>
<h3 id="section1">1. 見出し</h3>

しかし保存後に再度編集画面を開くと、

  • id属性が消える
  • classが消える場合もある

結果として、目次リンクが機能しなくなりました。


2. 原因

原因は、CKEditorのHTMLフィルタ機能です。

CKEditorはセキュリティ対策として、以下のような動作を行います。

  • 許可されていない属性を自動削除
  • 危険なタグ(scriptなど)を削除

これはXSS(クロスサイトスクリプティング)対策のための仕様です。

参考(公式ドキュメント):
https://ckeditor.com/docs/


3. 解決方法

解決方法は、CKEditorの設定で「許可するHTML」を指定することです。CKEditorの設定はsettings.pyに記載します。

方法①:すべて許可

CKEDITOR_CONFIGS = {
    'default': {
        'allowedContent': True,
    },
}

この設定により、HTMLの制限が解除されます。
idやclassもそのまま保存されるようになります。

方法②:必要なものだけ許可

CKEDITOR_CONFIGS = {
    'default': {
        'extraAllowedContent': 'h2[id]; h3[id]; a[class,href];',
    },
}

この設定では以下を許可します:

  • h2, h3 の id属性
  • aタグの class, href

必要なものだけ許可するため、セキュリティ的にも安全です。


4. 消えるその他の属性

id以外にも、以下の属性が消えることがあります。

  • class(CSS用)
  • style(インラインCSS)
  • data-* 属性

例えば:

<a href="#" class="btn btn-primary">ボタン</a>

これも設定次第では class が消えます。

そのため、Bootstrapなどを使う場合は特に注意が必要です。

必要に応じて以下のように追加します。

'extraAllowedContent': 'a[class,href];'

5. おわりに

ブログで目次リンクを使う場合、id属性は必須です。
同じ問題で悩んでいる方は、ぜひ設定を見直してみてください。

追記:CKEditor4はサポートが終了しているためCKEditor5を使うようにしましょう。