-->
How To Upload An Image Ckeditor Flask Alternative/ Summernote Image Upload Flask Python / Ckeditor Alternative

How To Upload An Image Ckeditor Flask Alternative/ Summernote Image Upload Flask Python / Ckeditor Alternative

Back to top

Updated by Ashirafu Kibalama on September 16, 2024

Ckeditor Alternative: Upload An Image Ckeditor Flask Alternative/ Summernote Image Upload Flask Python




This blog post discusses the importance of image upload functionality in Content Management Systems (CMS) for creating engaging user experiences in web development. 

This post highlights that integrating this feature with popular text editors like Summernote and CKEditor can be challenging for developers.


It can lead to issues like "summernote image upload not working" or "ckeditor image upload not working." 


The blog offers a comprehensive guide to integrating Summernote as an alternative:


 To ckeditor image upload not working with Flask, providing solutions to common stumbling blocks. 


The post concludes by emphasizing that the guide is a roadmap to success for developers encountering hurdles with image uploads in Summernote.


Or CKEditor or seek an accessible and efficient image upload solution for their Flask application.


We are to cover two parts:

Part 1: 

Using a Summernote CDN


Part 2:

Download the Summernote source code and make it available on your website.


This is important because we future-proof your website in cases when Summernote management decides to make their service premium (paid for).


As of the time of creating this post, Summernote service is free of charge.


Part 1: Summernote Image Upload Python Using a Summernote CDN:


#Page screenshot with CKEditor before Summernote CDN:







#Codes with CKEditor before Summernote CDN:


#create-post.html


{% from "bootstrap5/form.html" import render_form %}

{% include "header.html" %}


<!-- Page Header-->

<!-- Post Content -->

<div class="container">

<main class="container">


<div class="row mb-2">


</div>

<div class="row g-5">
<div class="col-md-8">

<!-- Articles Starts -->

<article class="blog-post">
<!-- Create Post -->

{{ ckeditor.load() }} {{ ckeditor.config(name='body') }} {{
render_form(form, novalidate=True, button_map={"submit": "primary"}) }}

</article>

<!-- Articles Ends -->


</div>

</div>

</main>

</div>

{% include "footer.html" %}


#main.py




# OTHER CODES ABOVE

# WTForm for creating posts
class CreatePostForm(FlaskForm):
title = StringField("Post Title", validators=[DataRequired()])
description = StringField("Description", validators=[DataRequired()])
author = StringField("Author Name", validators=[DataRequired()])
body = CKEditorField("Post Content", validators=[DataRequired()])
submit = SubmitField("Submit")


# CONFIGURE TABLE
# CREATE TABLE IN DB FOR POSTS
class Posts(db.Model):
id: Mapped[int] = mapped_column(Integer, primary_key=True)
title: Mapped[str] = mapped_column(String(300), unique=True, nullable=False)
description: Mapped[str] = mapped_column(String(250), nullable=False)
date: Mapped[str] = mapped_column(String(250), nullable=False)
body: Mapped[str] = mapped_column(Text, nullable=False)
author: Mapped[str] = mapped_column(String(250), nullable=False)

# OTHER CODES BELOW

#header.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="description" content="" />
<meta name="author" content="" />
<title>freepythonsourcecode</title>
{% block styles %}
<!-- Load Bootstrap-Flask CSS here -->
{{ bootstrap.load_css() }}
<link
rel="icon"
type="image/x-icon"
href="{{ url_for('static', filename='assets/favicon.svg') }}"
/>
<!-- Font Awesome icons (free version)-->
<script
src="https://use.fontawesome.com/releases/v6.3.0/js/all.js"
crossorigin="anonymous"
></script>
<!-- Google fonts-->
<link
href="https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic"
rel="stylesheet"
type="text/css"
/>
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
rel="stylesheet"
type="text/css"
/>
<!-- Bootstrap core JS-->

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

<link
href="{{ url_for('static', filename='css/styles.css') }}"
rel="stylesheet"
/>
{% endblock %}
</head>
<body>

<div class="container">
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-body-emphasis text-decoration-none">
<svg class="bi me-2" width="40" height="32"><use xlink:href="#bootstrap"></use></svg>
<span class="fs-4">Simple header</span>
</a>

<ul class="nav nav-pills">
<li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
<li class="nav-item"><a href="#" class="nav-link">Features</a></li>
<li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
<li class="nav-item"><a href="#" class="nav-link">FAQs</a></li>
<li class="nav-item"><a href="#" class="nav-link">About</a></li>
</ul>
</header>
</div>


#footer.html

<!-- Footer Starts -->

<div class="container">
<footer class="py-3 my-4">
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Home</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Features</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Pricing</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">FAQs</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">About</a></li>
</ul>
<p class="text-center text-body-secondary">© 2024 freepythonsourcecode.com</p>
</footer>
</div>

<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> <!-- Core theme JS-->
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
</body>
</html>


4 Steps For Summernote Image Upload Python Using a Summernote CDN:


Step 1:
Google search Summernote and click the Summernote official website:



Then click Getting started:




Then scroll down until this code snippet:


Step 2:
Modify your create-post.html code as illustrated below:

#First, in the imports, we also imported render_field so that you can handle each row of the form separately:

#The main reason is to handle the text area:

According to the summernote documentation, you are to include an #id of summernote to your textarea as illustrated below:

        <div class="form-group">
<label for="summernote"> Blog Content </label>
<textarea id="summernote" name="body" required>{{ form.body.data }}</textarea>
</div>


#full code for create-post.html code

{% from "bootstrap5/form.html" import render_form, render_field  %} {% block content %}

{% include "header.html" %}


<!-- Page Header-->

<!-- Post Content -->

<div class="container">

<main class="container">


<div class="row mb-2">


</div>

<div class="row g-5">
<div class="col-md-8">

<!-- Articles Starts -->

<article class="blog-post">
<!-- Create Post -->


<form action="" method="post" enctype="multipart/form-data">
<div class="container">
<div class="row">

{{ form.hidden_tag() }}
<div class="form-group">

{{ render_field(form.title, class="form-control") }}
</div>


<div class="form-group">

{{ render_field(form.description, class="form-control") }}
</div>
<div class="form-group">
{{ render_field(form.author, class="form-control") }}
</div>
<div class="form-group">
<label for="summernote"> Blog Content </label>
<textarea id="summernote" name="body" required>{{ form.body.data }}</textarea>
</div>

{{ form.submit(class="btn btn-primary float-right") }}
<!-- Update the following line to use Summernote -->
</div>
</div>

</form>

</article>

<!-- Articles Ends -->


</div>

</div>

</main>

</div>

{% include "footer.html" %} {% endblock %}


Step 3:
Include jQuery and Bootstrap libraries and summer CSS/js codes into your code:



<!-- include libraries(jQuery, bootstrap) -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<!-- include summernote css/js -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>


#header.html

    
<!-- OTHER CODES ABOVE -->

<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
rel="stylesheet"
type="text/css"
/>
<!-- Summernote stackpath bootstrap cdn css -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">

<!-- summernote css-->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">

<!-- Bootstrap core css-->

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">


<!-- css -->
<link
href="{{ url_for('static', filename='css/styles.css') }}"
rel="stylesheet"
/>
{% endblock %}
</head>
<body>

<!-- OTHER CODES BELOW -->


#footer.html


<!-- OTHER CODES ABOVE -->

<!-- summernote jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<!-- summernote stackpath bootstrap CDN-->

<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<!-- summernote css-->
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>

<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> <!-- Core theme JS-->
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>

</body>
</html>


Step 4:
Add the Summernote js code at the end of  your scripts.js code:



#scripts.js

// OTHER CODES ABOVE

<!-- Initialize Summernote -->

$(document).ready(function () {
$('#summernote').summernote({
height: 300, // Set the height of the editor
// Add other options as needed


});
});




#A problem to fix: 


The custom styles defined in styles.css do not override Bootstrap styles despite being placed after the Bootstrap stylesheet link; 


To ensure that your custom styles in styles.css take priority over Bootstrap styles:

 You can use the "!important" CSS declaration in your custom styles. 


Here's how you can modify your styles.css file to achieve this:


#styles.css


body {
font-size: 1.5rem !important;
}

/* OTHER CODES BELOW */


However, you can do it in the way of your choice: this is just CSS modification.








Part 2: Summernote Image Upload Python Using a Summernote source code downloaded:


8 Steps For Summernote Image Upload Python Using a Summernote source code downloaded:


Step 1:

Download the Summernote source code and extract it:


Step 2:
Go to your js folder and create a jquery.js:


Remember that you link this jquery script with a CDN:

#footer.html


<!-- OTHER CODES ABOVE -->

<!-- summernote jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

So go to this link and copy all the jquery codes and then paste them into your jquery.js:

#footer.html

https://code.jquery.com/jquery-3.5.1.min.js



Replace this line of code:

#footer.html

<!--    OTHER CODES ABOVE -->

<!-- summernote jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

with this line of code:

#footer.html


<!-- OTHER CODES ABOVE -->

<!-- summernote jQuery -->
<!--<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>-->


<script src="{{ url_for('static', filename='js/jquery.js') }}"></script>

Step 3:
Copy and paste summernote.min.js and summernote.mini.js.map into your js folder:




Then replace this code:

#footer.html



<!-- summernote css-->
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>

with this code:

#footer.html


<!-- summernote css-->
<!--<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>-->


<script src="{{ url_for('static', filename='js/summernote.min.js') }}"></script>



Step 4:
Go to your js folder and bootstrap.min.js file:


#footer.html


<!-- summernote stackpath bootstrap CDN-->

<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

Go to this link, copy and paste the code into the bootstrap.min.js file you created:

https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js



Then replace this code:

#footer.html


<!-- summernote stackpath bootstrap CDN-->

<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

with this code:

#footer.html


<!-- summernote stackpath bootstrap CDN-->

<!--<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>-->

<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>



# A complete footer.html code:

<!-- Footer Starts -->

<div class="container">
<footer class="py-3 my-4">
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Home</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Features</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Pricing</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">FAQs</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">About</a></li>
</ul>
<p class="text-center text-body-secondary">© 2024 freepythonsourcecode.com</p>
</footer>
</div>

<!-- OTHER CODES ABOVE -->

<!-- summernote jQuery -->
<!--<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>-->


<script src="{{ url_for('static', filename='js/jquery.js') }}"></script>

<!-- summernote stackpath bootstrap CDN-->

<!--<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>-->

<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>



<!-- summernote css-->
<!--<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>-->


<script src="{{ url_for('static', filename='js/summernote.min.js') }}"></script>



<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> <!-- Core theme JS-->

<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>

</body>
</html>


Step 5:
Copy and paste summernote.min.css to your css folder:


Then replace this code:

#header.html


<!-- summernote css-->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">

with this code:


<!-- summernote css-->
<!-- <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">-->

<link href="{{ url_for('static', filename='css/summernote.min.css') }}" rel="stylesheet"/>

Step 6:
Copy and paste the font folder to your css folder:



Step 7:
Create a file "bootstrap.min.css" with your css folder:


#header.html

<!-- Summernote stackpath bootstrap cdn css -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">

Go to this link, copy and paste the codes into your bootstrap.min.css file:

#header.html

https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css



Replace this code:

#header.html

    
<!-- Summernote stackpath bootstrap cdn css -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">

with this code:

#header.html


<!-- Summernote stackpath bootstrap cdn css -->
<!-- <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">-->

<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"/>

Also copy and paste summernote-bs4.css:



Step 8:
Add the Summernote js code at the end of  your scripts.js code:



#scripts.js

// OTHER CODES ABOVE

<!-- Initialize Summernote -->

$(document).ready(function () {
$('#summernote').summernote({
height: 300, // Set the height of the editor
// Add other options as needed


});
});




#A problem to fix: 


The custom styles defined in styles.css do not override Bootstrap styles despite being placed after the Bootstrap stylesheet link; 


To ensure that your custom styles in styles.css take priority over Bootstrap styles:

 You can use the "!important" CSS declaration in your custom styles. 


Here's how you can modify your styles.css file to achieve this:


#styles.css


body {
font-size: 1.5rem !important;
}

/* OTHER CODES BELOW */


However, you can do it in the way of your choice: this is just CSS modification.








#A complete header.html code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="description" content="" />
<meta name="author" content="" />
<title>freepythonsourcecode</title>
{% block styles %}
<!-- Load Bootstrap-Flask CSS here -->
{{ bootstrap.load_css() }}
<link
rel="icon"
type="image/x-icon"
href="{{ url_for('static', filename='assets/favicon.svg') }}"
/>
<!-- Font Awesome icons (free version)-->
<script
src="https://use.fontawesome.com/releases/v6.3.0/js/all.js"
crossorigin="anonymous"
></script>
<!-- Google fonts-->
<link
href="https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic"
rel="stylesheet"
type="text/css"
/>


<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
rel="stylesheet"
type="text/css"
/>

<!-- Summernote bs4 css-->
<link rel="stylesheet" href="{{ url_for('static', filename='css/summernote-bs4.css') }}">

<!-- Summernote stackpath bootstrap cdn css -->
<!-- <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">-->

<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"/>


<!-- summernote css-->
<!-- <link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet">-->

<link href="{{ url_for('static', filename='css/summernote.min.css') }}" rel="stylesheet"/>


<!-- Bootstrap core css-->

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">


<!-- css -->
<link
href="{{ url_for('static', filename='css/styles.css') }}"
rel="stylesheet"
/>
{% endblock %}
</head>
<body>


<div class="container">
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-body-emphasis text-decoration-none">
<svg class="bi me-2" width="40" height="32"><use xlink:href="#bootstrap"></use></svg>
<span class="fs-4">Simple header</span>
</a>

<ul class="nav nav-pills">
<li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
<li class="nav-item"><a href="#" class="nav-link">Features</a></li>
<li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
<li class="nav-item"><a href="#" class="nav-link">FAQs</a></li>
<li class="nav-item"><a href="#" class="nav-link">About</a></li>
</ul>
</header>
</div>



Our guide offers a clear roadmap to integrate Summernote as an alternative editor.

You have learned how to address issues like " summernote image upload not working" and "CKEditor image upload not working" with Flask.

With our guide, you can use Summernote via CDN or download its source code for website availability.

You'll easily navigate and easily overcome challenges associated with image uploads.

This valuable resource ensures smoother development processes and enhanced user experiences for Flask applications.

Let us know how this guide helped you in the comment section below:

Happy coding!

Other Posts: