In this tutorial, you’ll learn how to save form data into a JSON database, handle validation properly, and implement a clean redirect after submission. By the end, your contact form won’t just collect messages—it will securely store them like a real web application.
Prerequisite:This tutorial is part of the Flask CKEditor Project Series.
📚 View the Complete Flask CKEditor Series
PreliminaryBefore I begin, it is recommended that you activate the virtual environment and install the relevant dependencies.
python -m venv venv
venv\Scripts\activate
pip install flask tinydb
Then, we need to set up the file and folder structure, as below:- TinyDB is a pure Python database that stores data in a simple JSON file.
- It feels like working with Python dictionaries and lists.
- TinyDB is small and fast for low to medium data volumes.
- All data is stored in a readable
.jsonfile. - You don’t need to learn SQL queries.
- TinyDB works smoothly inside Flask apps without needing external database services like MySQL or PostgreSQL
from flask_wtf import FlaskForm
from wtforms import StringField, BooleanField, SubmitField
from wtforms.validators import DataRequired
from flask_ckeditor import CKEditorField
class ContactForm(FlaskForm):
name = StringField('Name:', validators=[DataRequired()])
email = StringField('Email:', validators=[DataRequired()])
subscribe = BooleanField("Subscribe to our newsletter?")
message = CKEditorField('Message:', validators=[DataRequired()])
submit = SubmitField("Submit ☺️")
In order to ensure the message field is accepted and validated under the WTF. I need to import the CKEditorField, assign it to the message field, and set the validator as data required.<form method="POST" action="{{ url_for('submit') }}">
{{ form.hidden_tag() }}
<p>{{ form.name.label }} {{ form.name(size=32) }}</p>
<p>{{ form.email.label }} {{ form.email(size=32) }}</p>
<p>{{ form.message.label }} {{ form.message() }}</p>
{{ ckeditor.load() }}
{{ ckeditor.config(name='message') }}
<p>{{ form.subscribe() }} {{ form.subscribe.label }}</p>
<p class="submit-container">{{ form.submit(class="btn-submit") }}</p>
</form>
The form action refers to the submit() function on the app.py (we will set it up later on), and I am also adding an additional 'form.message()' widget on the contact.html. from flask import (Flask, render_template, redirect,
url_for)
from tinydb import TinyDB
# The JSON file output path
db = TinyDB('flask_ckeditor/message.json')
def submit():
# Create an instance of the ContactForm
form = ContactForm()
# Check if the form is submitted and passes validation
if form.validate_on_submit():
# Retrieve data from each form field
name = form.name.data
email = form.email.data
subscribe = form.subscribe.data
message = form.message.data
# Insert the form data into the database
db.insert({
'name': name,
'email': email,
'subscribe': subscribe,
'message': message
})
# Redirect the user to the thank you page after successful submission
return redirect(url_for('thankyou'))
# If form is not submitted or validation fails,
# re-render the contact page and display validation errors
return render_template('contact.html', form=form)@app.route('/thankyou')
def thankyou()
# render to thankyou page
return render_template('thankyou.html')
The thankyou.html is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Submitted Successfully</title>
<style>
h1 {
colour: red;
text-align: centre;
font-family: Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Your message has been sent successfully! 😊</h1>
</body>
</html>
Here is the thankyou.html view:

print(db.all())Submissions are saved securely, and users see a thank-you page after sending.
This setup makes your contact form fully functional and ready for small web apps or projects.
🎁 Get Your FREE Flask Cheat Sheet
Join 500+ Python learners and receive this printable Flask Cheat Sheet instantly. Plus, get new Flask tutorials delivered to your inbox.
✓ Practical coding tutorials
✓ Automation tips for SMEs
✓ New project ideas and templates
About the Author
Kelvin Loh is a Python developer focused on Flask, desktop applications, and business automation solutions. He shares practical tutorials and real-world coding projects to help developers and small businesses build useful applications.




Comments