なにをやったのか
完成形
- django template にWYSIWYGを導入したくて django-ckeditor を入れてみた
- デフォルトだと画像の埋め込みがURLリンクからしかできなかったので、ローカルストレージからアップロードできるようにした
- アップロード画面が日本語化されていなかったので自前で上書きして日本語化した
- 重たい画像をアップロードした時、画面が動かないので動作しているかが不明 -> ローディングイメージを実装
環境など
- macOS Mojave 10.14.6
- django-ckeditor 5.8.0
どうやるのか
django-ckeditorまわりの設定
インストールと注意点
- リポジトリのREADME にある通りではありますが、普通に
pip install django-ckeditor
します。 - djangoのsettings.py内の
INSTALLED_APPS
にckeditor
を追加します。 - もしcollectstaticコマンドが実行できる設定がされていなければ、同じくsettings.pyに
STATIC_ROOT
の記述を加え、python manage.py collectstatic
します。 - django-admin以外のTemplateで使用する場合は、Templateに
{{ form.media }}
を記載する必要があります。下記はその例です。
(私はこの設定で小一時間ハマりました…)
<h2>ブログ記事登録</h2>
<form method="POST" enctype="multipart/form-data">
{{ form.media }}
{{ form.as_p }}
{% csrf_token %}
<button type="submit">登録する</button>
</form>
upload imageプラグインの適用
- djangoのsettings.py内の
INSTALLED_APPS
にckeditor_uploader
を追加します。 - 同じくsettings.pyに
CKEDITOR_UPLOAD_PATH = 'uploads/'
など、アップロードした画像を保存するパスを指定します。(これはMEDIA_ROOT配下のディレクトリになります) - 合わせて、画像ファイルのみのアップロードに制限する
CKEDITOR_ALLOW_NONIMAGE_FILES = False
を指定します。(画像以外もアップロードする場合はこの指定は不要) -
CKEDITOR_IMAGE_BACKEND = "pillow"
の指定をsettings.pyに記述することで、アップロードした画像のサムネイルを自動で生成してくれ、後に出てくる画像ブラウジングの際にサムネイルが表示されます。 - アプリのurlルーティングにckeditor uploaderの設定を追加します。
path('ckeditor/', include('ckeditor_uploader.urls'))
公式ドキュメントにもありますが、上記5で追加したurlのdecoratorとして@staff_member_required
が指定されているため、djangoのデフォルトUsermodelをカスタムしている場合にうまく動かない場合があります。(is_staffカラムを削除している場合など)
その場合は、ckeditor_uploader.urls
の中身をラップしてしまえばいいので、 公式のソースに倣ってurls.pyを作成し、それをincludeするようにします。
以下は@staff_member_required
の代わりにlogin_required
を使用する例です。
from __future__ import absolute_import
from django.conf.urls import url
from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import never_cache
from ckeditor_uploader import views
urlpatterns = [
url(r'^upload/', login_required(views.upload), name='ckeditor_upload'),
url(r'^browse/', never_cache(login_required(views.browse)), name='ckeditor_browse'),
]
ここまでの設定で画像がアップロードできるようになったと思います
自前で日本語化
デフォルトの状態
デフォルトの状態だと、まず不要なタブが多いですね。
こちらの記事を参考にして、必要最低限のタブだけに絞って日本語も自然に修正しています。
ckeditorのconfig.jsという設定関連のソースが static/ckeditor/ckeditor/config.js
にありますが、
こちらをそのまま編集すると後々面倒になりそうだったので、個別にjsを作成してそれを対象のtemplate側で読み込むようにしています。
CKEDITOR.on("dialogDefinition", function (ev) {
// 元記事の記述そのままのため中略
});
これだけだと、 サーバブラウザ
を開いたときに以下のように日本語化されていません。
これを日本語化していきます。
browserのtemplateを上書きする
公式ソースのviews.pyを見ると、 ckeditor/browse.html
をレンダリングしていることがわかります。
なので、公式ソースのbrowse.htmlを参考にして、必要な部分を日本語化します。
で、Djangoの適当なApp配下のtemplates内にckeditorのtemplateとして配置します。 (例: blog/templates/ckeditor/browse.html)
そうすることでライブラリのtemplatesではなく、オリジナルのtemplatesが使用されて表示されるようになります。
ローディングイメージを実装
画像をローカルから選択し、アップロードボタンを押すと容量の大きな画像の場合、アップロードに時間がかかり画面がしばらく切り替わらない状態となります。
ユーザーからすると何も動いていないように見えるので、アップロード中だということが分かるようローディングイメージを出そうと思います。
先程作成したckeditor_config.jsを編集し、以下を追加します。
CKEDITOR.on( 'instanceReady', function(ev){
const editor = ev.editor;
editor.on('fileUploadRequest', function(ev){
const fileLoader = ev.data.fileLoader;
// Notificationsをbindすることでメインの編集画面に通知が出るが、今回は別Dialogなのであまり意味がない。
// CKEDITOR.fileTools.bindNotifications(fileLoader.editor, fileLoader);
fileLoader.on("uploading", function () {
console.log("アップロード開始");
});
fileLoader.on("uploaded", function () {
console.log("アップロード完了");
});
fileLoader.on("error", function () {
console.log("アップロードエラー");
});
fileLoader.on("abort", function () {
console.log("アップロード失敗");
});
});
});
上記では、CKEDITORの instanceReady
イベントにhookして、ファイルアップロードWidgetである fileLoader
を取得し、
fileLoader
に定義されている各イベントごとにリスナーをセットしています。
これらのイベントにhookして、それぞれローディングイメージの表示/非表示を制御してあげればいいです。
さいごに
- ckeditorは導入自体は楽だけど、カスタマイズしようと思うと本家のソースとかまで読まないといけなくて結構大変。
- ただ、自前でWYSIWYG作るのはもっと大変なので、それに比べればすごい楽。
- 繰り返しになりますが、 こちらの記事には本当にお世話になりました。