Tinymce

How to Integrate Tinymce 5 with Flask (with csrf)


web development

This article shows how to integrate Tinymce 5 with Flask even including csrf protection!

Text area

<textarea id="content"></textarea>

Tinymce

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/5.10.2/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
    selector: '#content',
    plugins: [
        'advlist autolink link image imagetools lists charmap print preview hr anchor pagebreak spellchecker',
        'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking',
        'save table contextmenu directionality template paste textcolor codesample'
    ],
    imagetools_toolbar: "rotateleft rotateright | flipv fliph | editimage imageoptions",
    toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | print preview media fullpage | forecolor backcolor emoticons | codesample',
    relative_urls: false,
    images_upload_handler : function(blobInfo, success, failure) {
            var xhr, formData;

            xhr = new XMLHttpRequest();
            xhr.withCredentials = false;
            xhr.open('POST', '{{ url_for('upload_function_name_here') }}'); // change this

            xhr.onload = function() {
                var json;

                if (xhr.status != 200) {
                    failure('HTTP Error: ' + xhr.status);
                    return;
                }

                json = JSON.parse(xhr.responseText);

                // if (!json || typeof json.file_path != 'string') {
                //     failure('Invalid JSON: ' + xhr.responseText);
                //     return;
                // }

                success(json.location);
            };

            formData = new FormData();
            formData.append('file', blobInfo.blob(), blobInfo.filename());
            formData.append('csrf_token', '{{csrf_token()}}'); // i add csrf_token

            xhr.send(formData);
        },
    image_title: true,
    automatic_uploads: true,
    images_reuse_filename: false,
    images_upload_base_path: '/static/gallery/', // i serve from /static/gallery and save to /static/gallery
    codesample_languages: [
        { text: 'HTML/XML', value: 'markup' },
        { text: 'JavaScript', value: 'javascript' },
        { text: 'CSS', value: 'css' },
        { text: 'Processing', value: 'processing' },
        { text: 'Python', value: 'python' }
    ],
    width: "100%",
});
</script>

First add to config GALLERY_UPLOAD_PATH with value the absolute path of your static folder

flask

from flask import abort
from flask import current_app
from flask import Response
from flask import request
from flask import url_for
from flask import jsonify

from werkzeug.utils import secure_filename

@module_blueprint.route('/file-upload', methods=['GET', 'POST'])
def file_upload():
    """
    Upload post images from tinyMce editor.
    Save image to path.
    returns: json { location: path }
    """

    # Get the file user has uploaded inside the tinymce editor.
    uploaded_file = request.files.get('file')

    if uploaded_file:
        filename = secure_filename(uploaded_file.filename).lower()

        # Validate the contents of the file.  Check the header of the file is infact an image.
        # valid_img_ext = validate_img(uploaded_file.stream)

        # Split filename and extension, rename & add correct extension.
        # filename = secure_filename(os.path.splitext(filename)[0] + valid_img_ext)

        img_path = os.path.join(current_app.config['GALLERY_UPLOAD_PATH'], filename)

        # Check if user directory exists, create if nessecary.
        if not os.path.exists(current_app.config['GALLERY_UPLOAD_PATH']):
            try:
                os.makedirs(current_app.config['GALLERY_UPLOAD_PATH'])
            except OSError as e:
                if e.errno != errno.EEXIST:
                    raise

        # Save the image.
        uploaded_file.save(img_path)
        location = url_for('static', filename='gallery/' + filename)
        print(location)

        # Return image path back to editor
        return jsonify({'location': location})

    abort(Response('404 - Image failed to upload'))

Flask 2.x

Kevin7’s article was not working, adapted it

Written by

Abdur-Rahmaan Janhangeer

Chef

Python author of 7+ years having worked for Python companies around the world

Suggested Posts

How to implement beautiful notifications in Flask

Since you already know how to implement notifications, let’s see how to implement beautiful notifica...

Read article

How to implement notification in Flask

Implementing notifications in Flask goes way beyond using flash. You have to add this snippet in you...

Read article

How to integrate P5JS with Flask-SocketIO

P5Js is an implementation of processing.org’s library in JavaSript. It can be thought of as a canvas...

Read article
Free Flask Course