Basic Usage


$ pip install flask-ckeditor


This extension needs to be initialized in the usual way before it can be used:

from flask_ckeditor import CKEditor

app = Flask(__name__)
ckeditor = CKEditor(app)

This extension also supports the Flask application factory pattern by allowing you to create a CKEditor object and then separately initialize it for an app:

from flask_ckeditor import CKEditor

ckeditor = CKEditor()

def create_app():
    app = Flask(__name__)
    return app

Include CKEditor Resources

In the template in which you want to put a CKEditor textarea, call ckeditor.load() in <head></head> or before </body>:

    {{ ckeditor.load() }}

By default, it will load the CKEditor resources from CND (, you can set CKEDITOR_SERVE_LOCAL to True to use built-in resources. You can use custom_url to load your custom CKEditor build:

{{ ckeditor.load(custom_url=url_for('static', filename='ckeditor/ckeditor.js')) }}

CKEditor provides five types of preset (see comparison table for the differences):

  • basic
  • standard (default value)
  • full
  • standard-all (only available from CDN)
  • full-all (only available from CDN)

You can use pkg_type parameter or CKEDITOR_PKG_TYPE configuration variable to set the package type. For example:

{{ ckeditor.load(pkg_type="basic") }}


app = Flask(__name__)
app.config['CKEDITOR_PKG_TYPE'] = 'basic'
ckeditor = CKEditor(app)

This method is just a helper to generate <script> to include CKEditor resources, you can also write <script> element directly:

<script src=""></script>

Create a CKEditor Textarea

It’s quite simple, just call ckeditor.create() in the template:

<form method="post">
    {{ ckeditor.create() }}
    <input type="submit">

You can use value parameter to pass preset value (i.e. ckeditor.create(value='blah...blah...').

Get the Data

Since the CKEditor textarea is just a normal <textarea> element, you can get the data from request.form by passing ckeditor as key:

from flask import request, render_template

def new_post():
    if request.method == 'POST':
        data = request.form.get('ckeditor')  # <--

    return render_template('index.html')

Working with Flask-WTF/WTForms

When using Flask-WTF/WTForms, you can import the CKEditorField provided by Flask-CKEditor and use it just like StringField:

from flask_wtf import FlaskForm
from flask_ckeditor import CKEditorField
from wtforms import StringField, SubmitField

class PostForm(FlaskForm):
    title = StringField('Title')
    body = CKEditorField('Body')  # <--
    submit = SubmitField('Submit')

One more step is to call ckeditor.config() and pass the CKEditorField attribute’s name:

 <form method="post">
    {{ form.title() }}
    {{ form.body() }}
    {{ form.submit() }}

 {{ ckeditor.load() }}
 {{ ckeditor.config(name='body') }}

In the view function, you can get the data either by request.form.get('body') or


Check the demo application at examples/basic and examples/without-flask-wtf.

Preset Value in CKEditor Textarea

When you implement an edit feature for your CMS, you will need to get the article data from database, then preset the value into the CKEditor textarea. First you need to pass the value into template:

def edit_post():
    article_body = get_the_article_body_from_somewhere()
    return render_template('edit.html', article_body=article_body)

Then pass it to CKEditor with value parameter:

<form method="post">
    {{ ckeditor.create(value=article_body) }}
    <input type="submit">

If you are using Flask-WTF/WTForms, it’s even more simple, just pass the value to the form field’s data attribute:

def edit_post():
    form = EditForm() = get_the_article_body_from_somewhere()  # <--
    return render_template('edit.html', form=form)