简体   繁体   中英

AssertionError in Flask App when connecting to database using config in blueprint

I am building a Flask application which connects to an existing MySQL database as an exercise to learn Flask. I am encountering an error when trying to connect to the database, from a database object which is instantiated from a blueprint.

My Project structure is as follows

project
├─── instance
├─── config.py
├─── application
├─── _src
├─── db.py
├─── extensions.py
├─── admin
├─── templates
├─── __init__.py
├─── views.py
├─── static
__init__.py

My __init__.py (in the applications directory) has the following code:

from flask import Flask

# Config file
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile("config.py")

# Blueprints
from application.admin.views import adminBlueprint

# Register the blueprint
app.register_blueprint(adminBlueprint)

My Config file has the following:

#####################
# Database details ##
#####################
DB_USERNAME = "username"
DB_PASSWORD = "password"
DB_DATABASE_NAME = "databasename"
DB_HOST = "localhost"

The views file, in my admin folder has the following:

# Imports
from flask import render_template, Blueprint
from .._src.db import DB
from .._src import admin as admin

# Config
adminBlueprint = Blueprint("admin", __name__, template_folder="templates")

# Routes
@adminBlueprint.route("/admin")
def admin():
    # Connect to the database
    db = DB()
    cursor, conn = db.connectDB()
    # Get the required data
    projects = admin.getProjects(cursor, "all")
    # Close the database connection
    db.close()
    # Render data to the template
    return render_template("admin.html", projects=projects)

My extensions file, in the _src folder, which is used to allow access to the MySQL object from the blueprint, has the following code:

from flaskext.mysql import MySQL
mysql = MySQL()

And my db file in the _src directory has the following:

from flask import current_app
from .._src.extensions import mysql

class DB:
    def __init__(self):
        # Something will be done here in the future
        pass

    def connectDB(self):
        # Provide the database connection details
        current_app.config['MYSQL_DATABASE_USER'] = current_app.config["DB_USERNAME"]
        current_app.config['MYSQL_DATABASE_PASSWORD'] = current_app.config["DB_PASSWORD"]
        current_app.config['MYSQL_DATABASE_DB'] = current_app.config["DB_DATABASE_NAME"]
        current_app.config['MYSQL_DATABASE_HOST'] = current_app.config["DB_HOST"]
        mysql.init_app(current_app)
        # Connect to the database
        try:
            self.conn = mysql.connect()
            cursor = self.conn.cursor()
            # Return the cursor object
            return cursor, self.conn
        except:
            return False

    def close(self):
        self.conn.close()

I'm getting the following error:

AssertionError: A setup function was called after the first request was handled. This usually indicates a bug in the application where a module was not imported and decorators or other functionality was called too late. To fix this make sure to import all your view modules, database models and everything related at a central place before the application starts serving requests.

And the debugger is pointing to this file in the db file:

mysql.init_app(current_app)

I'm a little out of my depth and I don't really understand what the problem is. Can I only initialize the MySQL object from the same place that I initialize the Flask app? If so, how can I then access the MySQL object from the blueprint?

Any help is appreciated.

I was able to fix this by putting my app instantiation into my extensions file instead of my init file:

extensions.py

from flask import Flask
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile("config.py")

Then, in my database connection object, I can import the current app to get the settings:

from flask import current_app
from .._src.extensions import mysql

I also removed this line, as I am now achieving this in my extensions file:

mysql.init_app(current_app)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM