Django CKEditor

6.7.3 · active · verified Mon Apr 13

django-ckeditor integrates the CKEditor 4 WYSIWYG rich text editor into Django projects, providing `RichTextField`, `RichTextUploadingField`, `CKEditorWidget`, and `CKEditorUploadingWidget` for seamless content management in both the admin interface and custom forms. The library is currently at version 6.7.3 and follows Django's release cycle for compatibility updates, though it has an important deprecation warning regarding its bundled CKEditor 4 version.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `RichTextUploadingField` into a Django model and use the corresponding form and template. It includes the necessary `settings.py` and `urls.py` configurations, emphasizing the crucial `{{ form.media }}` in the template for CKEditor to render correctly. This example assumes a basic Django project structure with a `base.html` template. Remember to run `python manage.py makemigrations` and `python manage.py migrate` after defining the model, and `python manage.py collectstatic` to gather CKEditor's static files. For file uploads, ensure your `MEDIA_ROOT` and `MEDIA_URL` settings are correctly configured.

import os
from django.db import models
from django.forms import ModelForm
from django.shortcuts import render, redirect
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

# --- settings.py additions ---
# INSTALLED_APPS = [
#     # ... other apps
#     'ckeditor',
#     'ckeditor_uploader',
# ]
#
# MEDIA_URL = '/media/'
# MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Ensure BASE_DIR is defined
# CKEDITOR_UPLOAD_PATH = 'uploads/'
# CKEDITOR_CONFIGS = {
#     'default': {
#         'toolbar': 'full',
#         'height': 300,
#         'width': '100%',
#         'extraPlugins': 'codesnippet',
#     },
# }
#
# # --- urls.py additions (project level) ---
# # from django.urls import include, path
# # from django.conf import settings
# # from django.conf.urls.static import static
# #
# # urlpatterns = [
# #     # ... other urls
# #     path('ckeditor/', include('ckeditor_uploader.urls')),
# # ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


# --- app/models.py ---
from ckeditor_uploader.fields import RichTextUploadingField

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = RichTextUploadingField(blank=True, null=True)

    def __str__(self):
        return self.title

# --- app/forms.py ---
class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content']

# --- app/views.py ---
def create_article(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('article_list')
    else:
        form = ArticleForm()
    articles = Article.objects.all()
    return render(request, 'app/article_form.html', {'form': form, 'articles': articles})

def article_list(request):
    articles = Article.objects.all()
    return render(request, 'app/article_list.html', {'articles': articles})

# --- app/urls.py (within your app) ---
# urlpatterns = [
#     path('create/', create_article, name='create_article'),
#     path('', article_list, name='article_list'),
# ]

# --- app/templates/app/article_form.html ---
# {% extends 'base.html' %}
# {% block content %}
#     <h2>Create Article</h2>
#     <form method="post">
#         {% csrf_token %}
#         {{ form.media }} {# IMPORTANT: Renders CSS/JS for CKEditor #}
#         {{ form.as_p }}
#         <button type="submit">Save</button>
#     </form>
#     <hr/>
#     <h2>Articles</h2>
#     <ul>
#         {% for article in articles %}
#             <li>{{ article.title }}</li>
#         {% endfor %}
#     </ul>
# {% endblock %}

# --- app/templates/app/article_list.html ---
# {% extends 'base.html' %}
# {% block content %}
#     <h2>Articles</h2>
#     <ul>
#         {% for article in articles %}
#             <li><a href="#">{{ article.title }}</a></li>
#             <div>{{ article.content|safe }}</div> {# Use |safe to render HTML #}
#         {% empty %}
#             <li>No articles yet. <a href="{% url 'create_article' %}">Create one</a>.</li>
#         {% endfor %}
#     </ul>
# {% endblock %}

view raw JSON →