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