0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

備忘録 django-ckeditorの環境構築

Last updated at Posted at 2025-01-29

はじめに

django-ckeditorを触る機会があり組み込む作業で四苦八苦したので、簡単な検証環境を作り具体的な作業の流れを備忘録として残す

検証環境

本記事では仮想環境、ckeditorで検証している

 python -m venv ckeditor 
.\ckeditor\Scripts\activate  

django、django-ckeditor、pillowをあらかじめpip installしておく
(pillowは画像ファイルを扱うために必要)

PS C:\Python_Django_data\django_ckeditor_test\django_ckeditor_test> python -V
Python 3.13.0

pip install django
pip install django-ckeditor
pip install pillow

(ckeditor) PS C:\Python_Django_data\django_ckeditor_test> pip list
Package         Version
--------------- -------
asgiref         3.8.1
Django          5.1.5
django-ckeditor 6.7.2
django-js-asset 3.0.1
pillow          11.1.0
pip             24.2
sqlparse        0.5.3
tzdata          2025.1

最初に通常のTextFieldをhtmlに表示させる

django-ckeditorに対応させるためのbodyフィールドを作成する

models.py
class Test(models.Model):
    body = models.TextField(max_length=2000, verbose_name="本文")
forms.py
class TestForm(ModelForm):
        body = forms.TextInput()
views.py
class TestCreateView(View):
    def get(self, request):
        form = TestForm()
        return render(request, "testapp/form.html", {"form": form})
<!DOCTYPE html>
<html lang = "ja">
    <head>
        <meta chatset="utf-8"/>
        <title>CKEditor test</title>
    </head>
    <body>
        <h1>CKEditor test</h1>
        <form method = "POST">
            {% csrf_token %}
            {{ form.as_p }}
        </form>
    </body>
</html>

html上のbody項目の状態

WS000000.png

django-ckeditorを設定する

settings.pyにckeditorを追記する

settings.py
INSTALLED_APPS = [
    '',
    'ckeditor',
]

models.pyでフィールドタイプを変更する

models.py
from ckeditor.fields import RichTextField
class Test(models.Model):
    body = RichTextField(max_length=2000, verbose_name="本文")

forms.pyでwidgetを指定する

(エラーが出るので調べたらCharFieldにする必要があるとのこと)

forms.py
from ckeditor.widgets import CKEditorWidget
class TestForm(ModelForm):
        body = forms.CharField(widget=CKEditorWidget)

htmlの変更

{% load static %}
<!DOCTYPE html>
<html lang = "ja">
    <head>
        <meta chatset="utf-8"/>
        <link href="{% static 'ckeditor/ckeditor.css' %}" media="all" rel="stylesheet">
        <script src="{% static 'ckeditor/ckeditor-init.js' %}" data-ckeditor-basepath="{% static 'ckeditor/ckeditor/' %}" id="ckeditor-init-script"></script>
        <script src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
        <script src="{% static 'ckeditor/fixups.js' %}"></script>
        <title>CKEditor test</title>
    </head>
    <body>
        <h1>CKEditor test</h1>
        <form method = "POST">
            {% csrf_token %}
            {{ form.as_p }}
        </form>
    </body>
</html>

staticの部分はsettings.pyでINSTALLED_APPSにckeditor追記しため
C:\Python_Django_data\django_ckeditor_test\ckeditor\Lib\site-packages\ckeditor\static
を読んでいる
(その下にckeditor/ckeditor/ckeditor.js等が存在する)

モデルを変更したため再マイグレーション

python manage.py makemigrations
python manage.py migrate

html上のbody項目の状態

これでいくつかの項目は使用できる
WS000001.png

画像アップロードとフォントサイズの項目を表示させる

settings.pyへの追記

INSTALLED_APPS への'ckeditor_uploader'の追記

settings.py
INSTALLED_APPS = [
    '',
    'ckeditor_uploader',
]

設定の追記

settings.py
CKEDITOR_UPLOAD_PATH = 'uploads/'  # ここでは 'uploads/' を指定
CKEDITOR_ALLOW_NONIMAGE_FILES = False  # アップロードを画像のみに制限
CKEDITOR_IMAGE_BACKEND = "pillow"  #pip installした"pillow"を指定

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  # メディアファイルを保存するディレクトリ
MEDIA_URL = '/media/'  # メディアファイルにアクセスするためのURL

CKEDITOR_CONFIGSの追記
https://django-ckeditor.readthedocs.io/en/latest/ より

settings.py
CKEDITOR_CONFIGS = {
    'default': {
        'skin': 'moono',
        # 'skin': 'office2013',
        'toolbar_Basic': [
            ['Source', '-', 'Bold', 'Italic']
        ],
        'toolbar_YourCustomToolbarConfig': [
            {'name': 'document', 'items': ['Source', '-', 'Save', 'NewPage', 'Preview', 'Print', '-', 'Templates']},
            {'name': 'clipboard', 'items': ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo']},
            {'name': 'editing', 'items': ['Find', 'Replace', '-', 'SelectAll']},
            {'name': 'forms',
             'items': ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton',
                       'HiddenField']},
            '/',
            {'name': 'basicstyles',
             'items': ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']},
            {'name': 'paragraph',
             'items': ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-',
                       'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl',
                       'Language']},
            {'name': 'links', 'items': ['Link', 'Unlink', 'Anchor']},
            {'name': 'insert',
             'items': ['Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe']},
            '/',
            {'name': 'styles', 'items': ['Styles', 'Format', 'Font', 'FontSize']},
            {'name': 'colors', 'items': ['TextColor', 'BGColor']},
            {'name': 'tools', 'items': ['Maximize', 'ShowBlocks']},
            {'name': 'about', 'items': ['About']},
            '/',  # put this to force next toolbar on new line
            {'name': 'yourcustomtools', 'items': [
                # put the name of your editor.ui.addButton here
                'Preview',
                'Maximize',

            ]},
        ],
        'toolbar': 'YourCustomToolbarConfig',  # put selected toolbar config here
        # 'toolbarGroups': [{ 'name': 'document', 'groups': [ 'mode', 'document', 'doctools' ] }],
        # 'height': 291,
        # 'width': '100%',
        # 'filebrowserWindowHeight': 725,
        # 'filebrowserWindowWidth': 940,
        # 'toolbarCanCollapse': True,
        # 'mathJaxLib': '//cdn.mathjax.org/mathjax/2.2-latest/MathJax.js?config=TeX-AMS_HTML',
        'tabSpaces': 4,
        'extraPlugins': ','.join([
            'uploadimage', # the upload image feature
            # your extra plugins here
            'div',
            'autolink',
            'autoembed',
            'embedsemantic',
            'autogrow',
            # 'devtools',
            'widget',
            'lineutils',
            'clipboard',
            'dialog',
            'dialogui',
            'elementspath'
        ]),
    }
}

models.pyでフィールドタイプをアップロードに対応させる

models.py
from ckeditor_uploader.fields import RichTextUploadingField
class Test(models.Model):
    body = RichTextUploadingField(max_length=2000, verbose_name="本文")

urls.pyの変更

プロジェクトとアプリケーション、両方のurls.pyを変更する必要がある

urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.urls import include, path
from . import views

app_name = "testapp"
urlpatterns = [
    path("test/create/", views.test_create, name="test_create"),
    path('ckeditor/', include('ckeditor_uploader.urls')),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

下記行を追記する必要がある

urls.py
    path('ckeditor/', include('ckeditor_uploader.urls')),
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

モデルを変更したため再マイグレーション

python manage.py makemigrations
python manage.py migrate

html上のbody項目の状態

settings.pyのCKEDITOR_CONFIGで設定した項目が表示され、フォントサイズが変更可能になっている。
WS000003.png

右のイメージアイコンから画像のプロパティを開きアップロードタブから画像ファイルをアップロードできる
WS000004.png

画像が表示される
WS000005.png

アップロードした画像ファイルは プロジェクトフォルダ\media\uploads\yyyy\mm\dd に格納される
WS000006.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?