Using MySQL with Flask
======================
.. currentmodule:: flask_mysqldb
Flask and MySQL have a nice partnership. With an easy setup, Flask can connect to your MySQL database. Inserting,
updating, deleting, and selecting data from MySQL can all be done in one simple setup.
Installation
------------
Install and update using `pip `_::
$ pip install mysqlclient
$ pip install flask-mysql
A Minimal Application
---------------------
In order to have MySQL integrated with Flask, the flask module needs to be imported with Flask and flask_mysqldb needs
to be imported with MySQL. For the purpose of this document rendor_template, request, redirect, url_for will also be
used from the module flask. Below is a snippet that can be used for this implementation::
from flask import Flask, rendor_template, request, redirect, url_for
from flask_mysqldb import MySQL
To get things up and running, the flask app needs to be setup. Also, the MySQL configuration needs to have the MySQL
credentials. The following is the basic setup that is needed to connect MySQL to Flask. This can be placed at the top
of the routes file that will handle MySQL data and below the modules that are imported.
Be sure to fill in the proper credentials for host, port, user, and password, database name::
app = Flask(__name__)
app.config['MYSQL_HOST'] = 'HOST'
app.config['MYSQL_PORT'] = 'PORT'
app.config['MYSQL_USER'] = 'USER'
app.config['MYSQL_PASSWORD'] = 'PASSWORD'
app.config['MYSQL_DB'] = 'DATABASE NAME'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
mysql = MySQL(app)
It is recommended that you set app.config['MYSQL_CURSORCLASS'] = 'DictCursor' to easily parse form data passed to Flask.
This makes all incoming form data passed as a dictionary style object. It is very similar to a dictionary but not a true
dictionary. Each field in the form is a key and the input is the value assigned to the key. Also, the information from
database can be passed to HTML templates and easily used in the Jinja syntax. This tutorial assumes DictCursor has been
setup.
Selecting Database Information and Displaying it
------------------------------------------------
To grab data from the database, a cursor needs to be opened and saved to variable name of your choice using
mysql.connection.cursor(). To perform a select statement, place it within .execute(). To pull everything after a
statement execution, the command .fetchall() can be used and saved to a dictionary style variable with name of your
choosing. After the data is saved to a variable, be sure to close the cursor with .close() so the connection is
properly closed. The information pulled from MySQL can be placed within the render_template function in the return
statement. This will send the data to the desired HTML template to be displayed to users. The following snippet shows an
example of MySQL table named Customers and the data being rendered to a page called customers.html. It is also placed
in a function named customers() with the Flask route decoration to page /customers/::
@app.route('/customers/', methods=['POST','GET'])
def customers():
cur = mysql.connection.cursor()
cur.execute("SELECT * FROM customers")
customers = cur.fetchall()
cur.close()
return render_template('customers.html', customers=customers)
The MySQL data has now been passed to the customers.html file. In order to display the data, the Jinja syntax is used.
The Jinja syntax is used to parse data from the customers object passed in rendor_tmplate. Below is an example of
how Jinja syntax can be used to display the MySQL data in an html data format::
| Customer ID |
First Name |
Last Name |
Phone Number |
{% for customer in customers %}
| {{ customer.customer_id }} |
{{ customer.first_name }} |
{{ customer.last_name }} |
{{ customer.phone_number }} |
If only certain fields or specific entries need to be pulled, the fields can be placed instead of the * and using the where
clause can filter out unneeded entries. Below is an example of pulling only first_name and last_name where customer_id
is some input saved in cid::
cur.execute("SELECT first_name, last_name FROM customers WHERE customer_id = %s", (cid))
Creating and Inserting Data into a Database Table
-------------------------------------------------
Flask can gather data from an HTML form, pass it a to Flask route, and then use MySQL to insert data into a table.
This is where the url_for is used to pass html form data to Flask. Below is an example of a simple form for capturing
data and passing it to a Flask route. The form is using Bootstrap for styling::
Within the form action, the Jinja syntax {{ url_for('update_customer') }} will pass what is captured in the form to
the route update_customer. Each id in the input will be the key in the dictionary style object that will be used to
insert data into the table. Below is the route and associated function that the information in the form is sent to::
@app.route('/add_customer/', methods=['POST', 'GET'])
def add_customer():
if request.method == 'POST':
fname = request.form['fname']
lname = request.form['lname']
phone = request.form['phone']
cur = mysql.connection.cursor()
cur.execute("INSERT INTO customers (first_name, last_name, phone_number) VALUES (%s, %s, $s)", (fname, lname, phone))
mysql.connection.commit()
cur.close()
return redirect(url_for('customers'))
The above snippet is the route, add_customer, that was used in the action= of the form. As mentioned before, it is
passed in a dictionary type object. Within the add_customer function, the request module is used. The POST method needs
to be checked to make sure the POST was used in the form. Each field is pulled by the id used in the form. In the
snippet, fname = request.form['fname'] will pull the valude form key 'fname' and assign it to a Python variable called
fname. As with the select, a cursor needs to be opened. Once the cursor is opened, the Python variables can be placed
into the execute command. Using **"INSERT INTO customers (first_name, last_name, phone_number) VALUES (%s, %s, $s)",
(fname, lname, phone)** is the same as running **INSERT INTO customers (first_name, last_name, phone_number) VALUES
('John', 'Smith', '8005882300')**. In Python syntax, the variables fname, lname, and phone will be placed in %s. The app need needs
to commit the changes and close the cursor. In the return statement, redirect and url_for will jump back to the customers
function and then the data will be pulled and displayed on the page customers.html page.
Deleting an Entry from a MySQL Table
------------------------------------
Deleting an entry is very simple. A user can select a database entry by the primary key and use Python SQL syntax to
delete the object. Building on the select statement section, a delete option can be implemented for each row. Below,
is an updated version of the HTML table that includes the field for delete::
| Customer ID |
First Name |
Last Name |
Phone Number |
Delete |
{% for customer in customers %}
| {{ customer.customer_id }} |
{{ customer.first_name }} |
{{ customer.last_name }} |
{{ customer.phone_number }} |
Delete Customer |