Integrating MySQL with Flask, pandas and pythonanywhere
Sometimes a spark comes from seemingly nowhere. That's when you reach for your tools and create. After a series of successful experiments, I decided this stack might be my quickest, best shot to get a functional website up and running in Python. I was pleasantly surprised to make rapid progress over the span of a quarantine weekend. Here are the steps to create a MySQL backed website with Flask.
Hosting With pythonanywhere
pythonanywhere is a web hosting service like GoDaddy. If you host your app with them, MySQL is the default database. Postgres integration is available at higher price tiers.
To get your Flask app's database up and running you need to:
- Create your database (see the "Databases" tab in pythonanywhere)
- Use the mysql terminal to create your tables
- Use the mysql.connector API to connect to your table and execute SQL from your Flask app.
Essential MySQL Terminal Commands
Show MySQL Version
1 | SELECT VERSION(); |
List tables in a database
1 | SHOW TABLES; |
Show All MySQL Variable Values
1 | SHOW VARIABLES; |
Creating a Table
1 | CREATE TABLE Marijuana (id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(350), date VARCHAR(350)); |
Create a Table with a JSON column
1 2 3 4 5 6 | CREATE TABLE Marijuana ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `store` varchar(200) NOT NULL, `details` json DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; |
Add New Column and specify column to insert AFTER
1 2 | ALTER TABLE Marijuana ADD COLUMN date VARCHAR(100) AFTER other_column; |
Alter Datatype of a Column
1 | ALTER TABLE Marijuana MODIFY id INT AUTO_INCREMENT PRIMARY KEY; |
Describe a Table
1 | DESCRIBE Marijuana; |
View All Records in a Table
1 | SELECT * from Marijuana; |
Select 10 Newest Records
1 | SELECT * from Marijuana ORDER BY id DESC LIMIT 10; |
"Explaining" A Query
1 | EXPLAIN SELECT * from Marijuana; |
Using "ANALYZE TABLE" tooptimize themis periodically recommended by MySQL:
1 | ANALYZE TABLE Marijuana; |

Installing Libraries in PythonAnywhere
You can use pip to install python libraries within the PythonAnywhere bash terminal. Go to the consoles tab and start a new bash terminal. Then to install a library, such as pandas:
python -m pip3.8 install --user pandas
Flask app with mysql.connector API, SQL and pandas
A Flask app making a mysql database connection with pandas:
- Creating an error log with logging.
- Connecting to a mysql database hosted through Flask and pythonanywhere
- Then reading a table to a pandas dataframe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import mysql.connector from flask import Flask import pandas as pd from datetime import date import logging import sys app = Flask(__name__) logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) @app.route("/") def hello_world(): """Call database and return data from df. Then display homepage.""" try: email_df = get_database_table_as_dataframe() print(email_df.shape) html_page = render_homepage() return html_page except: logging.exception("Failed to connect to database.") def render_homepage(): """Note: you should use Flask's render_template to render HTML files. However, for example you can make a quick f-string HTML page that works in this code. """ html_page = f"""<html><head><link rel='stylesheet' href="/static/styles/some_file.css"><link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico"> <Title>Dispensary Alerts</Title></head> <body><h2></h2> <p>Get alerts for your dope.</p><br> <h6><b>Sign Up</b></h6><br> <div class="form"> <form action="/add_signup_to_db" method="post" style="width:420px;text-align:center;display:block;" > <input type="text" name="Signup Form"> <input type="submit" value="Submit"> </form></div><br><br> <p><b>Current Time:</b> {str(date.today())} </p></body></html>""" return html_page def get_database_table_as_dataframe(): """Connect to a table named 'Emails'. Returns pandas dataframe.""" try: connection = mysql.connector.connect( host="username.mysql.pythonanywhere-services.com", db="username$DatabaseName", user="username", password="password", ) email_df = pd.read_sql(sql="""SELECT * FROM Emails""", con=connection) logging.info(email_df.head()) return email_df except: logging.exception("Failed to fetch dataframe from DB.") return "Oops!" @app.route("/add_signup_to_db", methods=["GET", "POST"]) def add_signup_to_db(email, date): """Pass data as SQL parameters with mysql.""" try: connection = mysql.connector.connect( host="username.mysql.pythonanywhere-services.com", db="username$DatabaseName", user="username", password="password", ) cursor = connection.cursor() sql = """INSERT INTO Emails (message, date) VALUES (%s, %s) """ record_tuple = (email, date) cursor.execute(sql, record_tuple) connection.commit() except mysql.connector.Error as error: logging.info("Failed to insert into MySQL table {}".format(error)) except: logging.exception("Error inserting records to DB.") finally: if connection.is_connected(): cursor.close() connection.close() return "MySQL connection is closed" |
Iterative Development
Below: making my website look less like a "my first HTML" website, experimenting with my app's message name and adding a sign-up form connected to the database.

Note: if you see this error when making a request in pythonanywhere:
OSError: Tunnel connection failed: 403 Forbidden
It's likely because you are "whitelisted" on the free plan. Upgrading to the $5/month plan will fix it!
Scoping The Full Stack
I'm really enjoying this web development stack. Here are all of the tools and library choices for this website:
- HTML
- CSS
- web framework: Flask library
- email: Flask-Mail library(SMTP)
- API calls to external websites: requests and json libraries
- data handling: MySQL database, mysql.connector API, pandas library
- file system: logging, os and sys libraries
- (may add) payment processing: Braintree Library
- web hosting: pythonanywhere
Finding Your Flask Groove
Flask is a little scary at first, but reasonable once you get a grasp of the basic syntax. Using the logging module to establish access, error and server log feeds was a big step to finding my Python traceback fixing groove. It's a work in progress.
Recapping My Python Web Development and Database Experiences
I previously created a website with web2py, another Python web framework like Flask and Django. I think it was a decent choice for me at that point in my Python journey. Back then, I connected a MongoDB back-end to web2py. I randomly picked Mongo out of the DB hat and it worked well enough.
My Python Web Development and Database Tools
App #1 web2py + MongoDB
App #2 Flask + MySQL
Future App? py4web + pyDAL + PostgreSQL
Future App? tornado + streamlit (or) Flask + Dash (+ SQLite)
Of these two diverse Python stacks, I favor MySQL and Flask. But I learned a lot from watching web2py's tutorial videos and it's less intimidating for beginners. And I barely scratched the surface of web2py's "pure Python" pyDAL (Database Abstraction Layer), which seems pretty dope.
web2py's creator has a new framework in progress called py4web. It has the same DAL and inherits many other web2py qualities. Definitely looking forward to exploring the DAL on my first py4web website. I'll likely use it to connect to PostgreSQL or SQLite. Maybe I'll install pyDAL with pip in the meantime.
Final Thoughts
Both of my websites are hosted with pythonanywhere, which gives you a text editor and bash terminal to run your scripts in a shell environment. I'm so pleased with all of these tools. They fit together smoothly and made creating my website a fun experience.