how to get flask-sqlalchemy to work with the application factory pattern

  • Last Update :
  • Techknowledgy :

Try this: In __init__.py, remove with app.appcontext(): db.create_all() and add import models to the bottom. Then add a management command to run.py. It'll look something like

app = create_app()

@app.cli.command()
def createdb():
   db.create_all()

Then

FLASK_APP = run.py flask createdb

__init__.py

from flask
import Flask, render_template
from flask_sqlalchemy
import SQLAlchemy
db = SQLAlchemy()
def create_app():
   app = Flask(__name__)
app.config.from_pyfile("../config.py")

db.init_app(app)
with app.app_context():
   db.create_all()

import auth
app.register_blueprint(auth.routes.auth, url_prefix = "/auth/")

return app

setup.py

from setuptools
import setup

setup(
   name = 'yourapplication',
   include_package_data = True,
   install_requires = [
      'flask',
   ],
)

auth/__init__.py

from flask
import Flask, Blueprint

import auth.routes
import auth.models

auth/routes.py

from flask
import Flask, Blueprint
from app
import db
from auth.models
import Researcher

auth = Blueprint("auth", __name__)

@auth.route("/insert")
def insert():
   #r = Reasearcher("Pat", "Den", "Pat_Den@mail.com", "operator", "Dr.", "Mr", "08611111", "+353", "0001")
r = Researcher("Dr.", "Mr", "08611111", "+353", "0001")
db.session.add(r)
db.session.commit()

@auth.route("/query")
def query():
   rs = Researcher.query.all()
s = ""
for r in rs:
   s += r.prefix + " " + r.phone
return s

Suggestion : 2

If you are already using packages and blueprints for your application (Modular Applications with Blueprints) there are a couple of really nice ways to further improve the experience. A common pattern is creating the application object when the blueprint is imported. But if you move the creation of this object into a function, you can then create multiple instances of this app later.,The downside is that you cannot use the application object in the blueprints at import time. You can however use it from within a request. How do you get access to the application with the config? Use current_app:,Call a function from a blueprint when the application is setting up so that you have a place to modify attributes of the application (like hooking in before/after request handlers etc.),It’s preferable to create your extensions and app factories so that the extension object does not initially get bound to the application.

def create_app(config_filename):
   app = Flask(__name__)
app.config.from_pyfile(config_filename)

from yourapplication.model
import db
db.init_app(app)

from yourapplication.views.admin
import admin
from yourapplication.views.frontend
import frontend
app.register_blueprint(admin)
app.register_blueprint(frontend)

return app
from flask
import current_app, Blueprint, render_template
admin = Blueprint('admin', __name__, url_prefix = '/admin')

@admin.route('/')
def index():
   return render_template(current_app.config['INDEX_TEMPLATE'])
def create_app(config_filename):
   app = Flask(__name__)
app.config.from_pyfile(config_filename)

db = SQLAlchemy(app)
db = SQLAlchemy()
def create_app(config_filename):
   app = Flask(__name__)
app.config.from_pyfile(config_filename)

from yourapplication.model
import db
db.init_app(app)
$
export FLASK_APP = myapp
$ flask run

Suggestion : 3

Create a Flask app using the 'Application Factory' pattern. Learn what an application context is and how to build large-scale apps properly.,Are you the type of person to start an app by first creating an app.py file in our base directory? If so, please stop - this simply isn't a realistic way to build production-ready applications. When we create an app which follows the Application Factory pattern, our app should look like this:,A properly configured Application Factory should accomplish the following:,Let's dig into it! We're going to create an example Flask application which utilizes some common patterns, such as connecting to a database utilizing a Redis store. This is is simply for demonstration purposes to show how all globally-accessible Flask plugins are initialized in a standard Flask app.

from flask
import Flask, render_template

app = Flask(__name__)
app.config['FLASK_DEBUG'] = True

@app.route("/")
def home():
   return render_template("index.html")

@app.route("/about")
def about():
   return render_template("about.html")

@app.route("/contact")
def contact():
   return render_template("contact.html")
/app├── / application│├── __init__.py│├── auth.py│├── forms.py│├── models.py│├── routes.py│├── / static│└── / templates├── config.py└── wsgi.py
from flask
import Flask
from flask_sqlalchemy
import SQLAlchemy
from flask_redis
import FlaskRedis

# Globally accessible libraries
db = SQLAlchemy()
r = FlaskRedis()

def init_app():
   ""
"Initialize the core application."
""
app = Flask(__name__, instance_relative_config = False)
app.config.from_object('config.Config')

# Initialize Plugins
db.init_app(app)
r.init_app(app)

with app.app_context():
   # Include our Routes
from.import routes

# Register Blueprints
app.register_blueprint(auth.auth_bp)
app.register_blueprint(admin.admin_bp)

return app
...

# Globally accessible libraries
db = SQLAlchemy()
r = FlaskRedis()

   ...
...

def init_app():
   ""
"Initialize the core application."
""
app = Flask(__name__, instance_relative_config = False)
app.config.from_object('config.Config')
...

def init_app():
   ...

   # Initialize Plugins
db.init_app(app)
r.init_app(app)

Suggestion : 4

Create an application factory pattern for initializing a Flask app,Configure Celery to work with the application factory pattern,Update app.py like so to create a Flask app using the above factory function:,create_app is a factory function, which can be called multiple times, that returns a Flask app for us to use

Flask - Migrate == 3.1 .0
Flask - SQLAlchemy == 2.5 .1
(env) $ pip install - r requirements.txt
import os

from flask
import Flask
from flask_migrate
import Migrate
from flask_sqlalchemy
import SQLAlchemy

# instantiate the extensions
db = SQLAlchemy()
migrate = Migrate()

def create_app():

   # instantiate the app
app = Flask(__name__)

# set up extensions
db.init_app(app)
migrate.init_app(app, db)

# shell context
for flask cli
@app.shell_context_processor
def ctx():
   return {
      "app": app,
      "db": db
   }

return app
from project
import create_app

app = create_app()
import os
from pathlib
import Path

class BaseConfig:
   ""
"Base configuration"
""
BASE_DIR = Path(__file__).parent.parent

TESTING = False
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL", f "sqlite:///{BASE_DIR}/db.sqlite3")

class DevelopmentConfig(BaseConfig):
   ""
"Development configuration"
""
DEBUG = True

class ProductionConfig(BaseConfig):
   ""
"Production configuration"
""
DEBUG = False

config = {
   "development": DevelopmentConfig,
   "production": ProductionConfig,
}
import os

from flask
import Flask
from flask_migrate
import Migrate
from flask_sqlalchemy
import SQLAlchemy

from project.config
import config # new

# instantiate the extensions
db = SQLAlchemy()
migrate = Migrate()

def create_app(config_name = None): # updated
# new
if config_name is None:
   config_name = os.environ.get("FLASK_CONFIG", "development")

# instantiate the app
app = Flask(__name__)

# new
# set config
app.config.from_object(config[config_name])

# set up extensions
db.init_app(app)
migrate.init_app(app, db)

# shell context
for flask cli
@app.shell_context_processor
def ctx():
   return {
      "app": app,
      "db": db
   }

return app

Suggestion : 5

The Flask application factory sounds complicated, but it can simply be defined as having a function return a configured instance of a Flask application, instead of instantiating one in the global scope. Traditionally the function is (very creatively) named create_app.,The function should return a Flask application object. In order to create a Flask application object, we will need to import Flask at the top of the file just like we have before (from flask import Flask) and then within the create_app function, we can initialize an application.,Flask gives us a powerful tool to be able to simply start building a web server with essentially three lines of code. This is great to start but as our application becomes more complicated, this simplicity can come back to bite us.,At this point, we have an extremely simple application factory, but it doesn't actually do anything. There are no routes that have been configured here, so that's what we'll do next.

stock_app /
   __init__.py
blueprints /
   home.py
stock.py
templates /
   ....
requirements.txt
Procfile
def create_app():
   return...
from flask
import Flask

def create_app():
   app = Flask(__name__)
return app
from flask
import Flask

from stock_app.blueprints.home
import home
from stock_app.blueprints.stock
import stock

def create_app():
   app = Flask(__name__)
app.register_blueprint(home)
app.register_blueprint(stock)
return app