pythonflaskmysql-python

Flask working outside of application context despite app being initialised


I am trying to query a simple MySQL DB using MySQLdb in Flask. I have the following code:

from flask import Flask, render_template
import json
from flask_mysqldb import MySQL

app = Flask(__name__)

mysql = MySQL()

app.config['MYSQL_DATABASE_USER'] = 'dbuser'
app.config['MYSQL_DATABASE_PASSWORD'] = 'xxxxxxxxxxxxx'
app.config['MYSQL_DATABASE_DB'] = 'calendar'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

db = mysql.connect()
cur = db.cursor()

When I run this code, I get the following error in the Apache log:

RuntimeError: working outside of application context

I have verified that I am creating my app object before placing any calls to MySQLdb and read a number of pages/docs, but I cannot fathom why my code is failing, as it seems the same as other examples (such as https://codehandbook.org/python-web-application-flask-mysql/ and https://code.tutsplus.com/tutorials/creating-a-web-app-from-scratch-using-python-flask-and-mysql--cms-22972)


Solution

  • mysql.connect() use current_app everywhere, so you have to call it inside of application context.

    Method 1: Push an application context temporarily

    with app.app_context():
        cur = mysql.connection.cursor()
    

    Normally, you needn't create the global object. Instead, you can create cur object inside view function.

    Method 2: Call it inside view function

    @app.route('/')
    def users():
        cur = mysql.connection.cursor()
        cur.execute('''SELECT user, host FROM mysql.user''')
        rv = cur.fetchall()
        return str(rv)
    

    If you have a bunch of view functions use this object, you can create a before request handler to create it.

    Method 3: Call it in before_request function, then you can access cur in all the view function directly

    @app.before_request
    def make_db():
        cur = mysql.connection.cursor()