In a world where time is in ever-diminishing supply, it’s often beneficial to use tools that save us the legwork required when working with content creation. One of those tools is WYSIWYG (What You See Is What You Get) editor which makes it easier for people who don’t know how to code their pages. This way we can spend more time focussing on ideas and less time fiddling around with formatting to make the content look aesthetically pleasing. It allows people without technical experience to quickly upload images and make links between pages using a visual interface which saves everyone precious time and ensures your website looks awesome!

CKEditor is a powerful and easy-to-use WYSIWYG. It allows users to edit content directly in the web browser, which is a vital feature for dynamic websites. In this article, we will walk through the steps to implement CKEditor in a Django application.

Contents

Installation and Setup

Before we start making our Django project, let us install the necessary libraries and other dependencies that we’ll need. I will be covering a lot of ground here but you should have some basic knowledge about Django to follow along. I assume that you have one running already! 

In this tutorial, I will be using CKEditor 5 specifically, which is the latest version of CKEditor and is hence the most feature-rich. Install CKEditor 5 with the following command:

pip install django-ckeditor-5

Next, open up your settings.py file and add CKeditor to your INSTALLED_APPS as shown below:

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

Now, this would be it for the settings part for most other WYSIWYG editors but, CKeditor requires some additional configurations. First if haven’t already set up the media files’ location, add them to the bottom of your settings file as shown:

import os 
MEDIA_URL='/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'media')

Next, add a CKEDITOR_UPLOAD_PATH setting to the project’s settings.py file. To use CKEditor for media editing you have to specify the path to a folder on your web server where media files containing images and other content will be stored. 

CKEDITOR_UPLOAD_PATH = "uploads/"

This setting specifies a relative path to your CKEditor media upload directory. By default, Django uses the file system storage backend (it will use your MEDIA_ROOT and MEDIA_URL).

Now, images will be uploaded to a folder in your MEDIA_ROOT called “uploads” and URLs will be created against MEDIA_URL.

Open up the urls.py file now and add django_ckeditor_5.urls to your URL patterns and make the other changes:

# urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ...
    path('ckeditor5/', include('django_ckeditor_5.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Here I have also made the view accessible by adding the MEDIA_URL and MEDIA_ROOT locations to the end of URL patterns, and the above lines are the required imports to make it work.

After doing all the previous steps, you can finally start implementing this in your models! Just import CKEditor 5 into your models and put the CKEditor5Field in place of any other models field. Here’s an example:

# app/models.py
from django.db import models
from django_ckeditor_5.fields import CKEditor5Field

class Page(models.Model):
    title=models.CharField(max_length=200,null=True)
    content = CKEditor5Field(null=True)

   
    def __str__(self):
        return self.title 

Now if you have already registered this model class in the admin.py file, you will now be able to see the WYSIWYG editor in the admin area. Just create a superuser account in your Django project and navigate to the admin dashboard, you should be able to see CKEditor on the content field of your model:

Something like this. As you can see it is very bare-bones at the moment and doesn’t have any major features. This is because we haven’t yet defined anything that we would like to use it for yet. There are a lot more things that we can add or adjust to it; our settings.py file is the point where most of the customization will happen.

Customization

Now for the customization! CKEditor 5 configuration can be modified by using the config.js file or created in-page when creating instances of CKEditor . but we recommend setting its configuration in-page while creating editor instances because it lets you avoid modifying the original distribution files in the CKEditor 5 installation folder, making it easy to upgrade.

To do this, use CKEDITOR_CONFIGS setting in your settings.py file that specifies all the CKEditor settings that you want to be made life in your editor. Here we have made a very basic configuration of the editor’s toolbar:

CKEDITOR_5_CONFIGS = {
    'default': {
        'toolbar': ['heading', '|', 'bold', 'italic', 'link',
                    'bulletedList', 'numberedList', 'blockQuote', 'imageUpload', ],

    }
}

To use this we would also have to reference this in our models, which could be done as so:

content = CKEditor5Field(config_name='default',null=True

Note: By specifying a default option, it’ll be applied to all objects even if you haven’t defined page-specific configurations.

And now our editor will look something like this:

As you can see all the functions that we specified in our settings are present here. But still, this is a bit lacking in any major features. If you want to make a fully custom version of your editor you can view their catalog of CKEDITOR config where they have specified all the config variables of CKEditor.

But, if you want just add all the necessary features you can add their predefined configurations and adjust them to your liking. Just past the following code to the bottom of your settings.py file and you’re good to go.

customColorPalette = [
        {
            'color': 'hsl(4, 90%, 58%)',
            'label': 'Red'
        },
        {
            'color': 'hsl(340, 82%, 52%)',
            'label': 'Pink'
        },
        {
            'color': 'hsl(291, 64%, 42%)',
            'label': 'Purple'
        },
        {
            'color': 'hsl(262, 52%, 47%)',
            'label': 'Deep Purple'
        },
        {
            'color': 'hsl(231, 48%, 48%)',
            'label': 'Indigo'
        },
        {
            'color': 'hsl(207, 90%, 54%)',
            'label': 'Blue'
        },
    ]

CKEDITOR_5_CUSTOM_CSS = 'path_to.css' # optional
CKEDITOR_5_CONFIGS = {
    'extends': {
        'blockToolbar': [
            'paragraph', 'heading1', 'heading2', 'heading3',
            '|',
            'bulletedList', 'numberedList',
            '|',
            'blockQuote', 'imageUpload'
        ],
        'toolbar': ['heading', '|', 'outdent', 'indent', '|', 'bold', 'italic', 'link', 'underline', 'strikethrough',
        'code','subscript', 'superscript', 'highlight', '|', 'codeBlock',
                    'bulletedList', 'numberedList', 'todoList', '|',  'blockQuote', 'imageUpload', '|',
                    'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'mediaEmbed', 'removeFormat',
                    'insertTable',],
        'image': {
            'toolbar': ['imageTextAlternative', 'imageTitle', '|', 'imageStyle:alignLeft', 'imageStyle:full',
                        'imageStyle:alignRight', 'imageStyle:alignCenter', 'imageStyle:side',  '|'],
            'styles': [
                'full',
                'side',
                'alignLeft',
                'alignRight',
                'alignCenter',
            ]

        },
        'table': {
            'contentToolbar': [ 'tableColumn', 'tableRow', 'mergeTableCells',
            'tableProperties', 'tableCellProperties' ],
            'tableProperties': {
                'borderColors': customColorPalette,
                'backgroundColors': customColorPalette
            },
            'tableCellProperties': {
                'borderColors': customColorPalette,
                'backgroundColors': customColorPalette
            }
        },
        'heading' : {
            'options': [
                { 'model': 'paragraph', 'title': 'Paragraph', 'class': 'ck-heading_paragraph' },
                { 'model': 'heading1', 'view': 'h1', 'title': 'Heading 1', 'class': 'ck-heading_heading1' },
                { 'model': 'heading2', 'view': 'h2', 'title': 'Heading 2', 'class': 'ck-heading_heading2' },
                { 'model': 'heading3', 'view': 'h3', 'title': 'Heading 3', 'class': 'ck-heading_heading3' }
            ]
        }
    }
}

Also, change the config_name in your models from default to extends:

content = CKEditor5Field(config_name='extends',null=True)

And it would look something like this after you’re done:

You can see all the necessary features are present here as well as some very useful ones such as the option to insert tables, media URLs, code blocks, sub, superscripts, etc.

Final Words

In this article, we’ve covered some great reasons as to why you should consider CKEditor as your WYSIWYG editor of choice and how you can implement it in your Django website. We hope you find this information useful when deciding on your website’s content management solution!

Here are some useful tutorials that you can read: