This tutorial shows how to convert a Flask web application into a desktop application using FlaskWebGUI together with PyInstaller. You will learn how to package your Python code, templates, and database into a standalone executable file. It also covers handling file paths and resolving common issues like missing templates after packaging. By the end, you’ll have a fully functional desktop app that runs without requiring a browser or Python installation. This method is ideal for distributing your Flask projects to end users easily.
Preliminary
Before I begin, please activate the virtual environment and install the required dependencies.
Then, we need to set up the file and folder structure, as below:
All files and folders remain the same as in the previous file structure, except that I have added a desktop icon, "my.ico," and amended app.py to convert the Flask script into a GUI script and later packaged the same app into an .exe file and a .db database. python -m venv venv
venv\Scripts\activate
pip install flaskwebgui pyinstaller
Step 1: Set up the GUI view from the Flask script
The purpose of installing FlaskWebGui is to create desktop applications with Flask; therefore, it is similar to Electron.js but built on the Flask Python framework.
Below I have shown my code:
from flask import (Flask, render_template, redirect,
url_for)
from form import ContactForm
from flask_ckeditor import CKEditor
import sqlite3
from flaskwebgui import FlaskUI as ui
import os
import sys
import sqlite3
db_path = os.path.join(os.getcwd(), "flask_ckeditor_desktop/message.db")
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS message (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT,
subscribe TEXT,
message TEXT
)
""")
conn.commit()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
app.config['CKEDITOR_PKG_TYPE'] = 'full-all'
ckeditor = CKEditor(app)
@app.route('/')
def index():
form = ContactForm()
return render_template('contact.html', form=form)
@app.route('/message', methods=['GET','POST'])
def submit():
form = ContactForm()
if form.validate_on_submit():
name = form.name.data
email = form.email.data
subscribe = form.subscribe.data
message = form.message.data
db_path = os.path.join(os.getcwd(), "message.db")
conn = sqlite3.connect(db_path)
c = conn.cursor()
try:
query = ("""INSERT INTO message
VALUES (:id, :name, :email, :subscribe, :message)""")
my_data = {
'id' : None,
'name': name,
'email': email,
'subscribe': subscribe,
'message': message
}
content = c.execute(query, my_data)
conn.commit()
print(f"Data Added ID: " + str(content.lastrowid))
except sqlite3.Error as e:
print(e)
return redirect(url_for('thankyou'))
return render_template('contact.html', form=form)
@app.route('/thankyou')
def thankyou():
return render_template('thankyou.html')
if __name__ == '__main__':
ui(app=app, server="flask", width=1000, height=1000).run()
In the previous tutorial, I separated the creation of the SQLite database.db from app.py; however, for simplicity in this tutorial, I will combine the creation of the SQLite database into app.py.What I do is import the FlaskWebGUI UI component and use it to show the dimensions of the app, such that both height and width are 1,000, and use the Flask web framework for GUI creation (last line of the Flask app).
Then, I will launch the app by inputting the following code in the terminal.
python flask_ckeditor/app.pyOnce the message.db is created, now I can comment on the following code since I don't need it anymore:
# conn = sqlite3.connect(db_path)
# conn.execute("""
#CREATE TABLE IF NOT EXISTS message (
# id INTEGER PRIMARY KEY AUTOINCREMENT,
# name TEXT,
# email TEXT,
# subscribe TEXT,
# message TEXT
#)
#""")
#conn.commit()
Step 2: Package the Flask script into a .exe and .db files using PyInstaller
If I need to distribute the desktop application, I need to package it before it is ready to use. PyInstaller is dependent on the respective operating system (OS); Windows has .exe, and macOS has .app, respectively. Since my computer is running Windows OS, I installed PyInstaller to package my Flask script and convert it into a .exe Windows executable file.
Before packaging,
I need to amend the Flask script so PyInstaller knows where to locate the other folder and file; this is important to avoid the error "TemplateNotFound." So, the following shows how I amended the Flask code:
2) --onefile: that PyInstaller extracts the file into one single .exe file.
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
app = Flask(
__name__,
template_folder=resource_path("templates")
)
The resource_path() is a dynamic file locator; it helps to locate the Flask templates, static folder, and database. In my case, it is a SQLite database. This will prevent common PyInstaller errors.
After I had amended the above code, I could package it by following the code in the PowerShell terminal.
pyinstaller --onefile --noconsole `
--add-data "flask_ckeditor_desktop\templates;templates" `
--add-data "flask_ckeditor_desktop\message.db;." `
--icon "Flask_ckeditor_desktop\my.ico" `
flask_ckeditor_desktop\app.py1) pyinstaller: run the PyInstaller,
3) --nonconsole: Console is helping us to display the error and debugging; however, here I choose to hide the 'black terminal' if I am satisfied that the application runs successfully.
4) --add-data "flask_ckeditor_desktop\templates": Request the PyInstaller from the flask_ckeditor_desktop folder and find the contact.html and thankyou.html files to include in the .exe folder.
5) --add-data "flask_ckeditor_desktop\message.db": Request the PyInstaller from the flask_ckeditor_desktop folder and find the message.db file to include in the .exe folder.
6) --icon "Flask_ckeditor_desktop\my.ico": Requests the PyInstaller from the Flask_ckeditor_desktop folder, finds the desktop icon to include in the .exe folder, and shows the icon as a desktop shortcut.
7) Flask_ckeditor_desktop\app.py: Requests PyInstaller from the Flask_ckeditor_desktop folder to find the Flask main entry file. Thus, PyInstaller starts from here and bundles everything needed.
The app.exe output file will appear in the dist folder.
Here is my result for the app.exe Windows executable file:
Final wrap-up:
In this tutorial, you learned how to transform a Flask web application into a standalone desktop app using FlaskWebGUI and PyInstaller. You explored how to bundle templates, configure file paths correctly, and customise your executable with an icon. Key challenges like missing templates and database handling were also addressed. By applying these steps, you can confidently package and distribute your Flask apps as user-friendly desktop applications.




Comments
Post a Comment