Importing Flask app when using app factory and flask script - flask

This is Flask app context
app = Flask(__name__)
with app.app_context():
# insert code here
Most of the use cases of app context involves having 'app' initialized on the same script or importing app from the base.
My application is structured as the following:
# application/__init__.py
def create_app(config):
app = Flask(__name__)
return app
# manage.py
from application import create_app
from flask_script import Manager
manager = Manager(create_app)
manager.add_command("debug", Server(host='0.0.0.0', port=7777))
This might be really trivial issue, but how I should call 'with app.app_context()' if my application is structured like this?

Flask-Script calls everything inside the test context, so you can use current_app and other idioms:
The Manager runs the command inside a Flask test context. This means that you can access request-local proxies where appropriate, such as current_app, which may be used by extensions.
http://flask-script.readthedocs.org/en/latest/#accessing-local-proxies
So you don't need to use with app.app_context() with Manager scripts. If you're trying to do something else, then you'd have to create the app first:
from application import create_app
app = create_app()
with app.app_context():
# stuff here

Related

Flask set #app decorator outside main module

How do you set an #app... decorator outside of the main module?
I'm sorry if this a dumb question, but I am completely lost.
I wish to be able to decorate functions with #app.context_processor all over the place in a larg-ish app. All the examples I can find have these in main module, where app is defined. Thus in main.py I have e.g.
from app import create_app
app = create_app()
#app.context_processor
def test_me():
return {'test_me': 'test_me!!!'}
and in __init__.py I have
def create_app(config_class=Config):
app = Flask(__name__)
return app
That's fine, but how do I do same in some other module? app is not defined.
Let's say I have just that def test_me() in some other module. The module (presently) has no imports, doesn't use blueprints, etc.
Most questions asking about "how to access app in another module" use from flask import current_app, but you can only use current_app during a request, such as inside a def. Attempting to somehow use it for a decorator will give you the "not available in this context`, so that's not the way to go.
To answer my own question.
I needed to move the
app = create_app()
out of main.py and into __init__.py. Then app is visible to every module, and each one can go
from app import app
#app.context_processor
def something():
return {'something': 'something'}

How to get a handle to the initialized database from a Flask application with SQLAlchemy?

I would like to add data to a database with Flask-SQLAlchemy without the Flask app running.
Is there a way to get db back from the app after the app and the database have been initialized.
My code looks like
db = SQLAlchemy()
def init_app():
app = Flask(__name__)
db = SQLAlchemy(app)
db.init_app(app)
return app
And what I would like to do is something like
from app import init_app
app = init_app() # initialized but not running
# db is used in model.py, but not initialized
# with Flask
# from db = SQLAlchemy()
from model import Machine # class Machine(db.Model)
p = Machine(name='something')
# now I need the initialized db from somewhere
db.session.add(p)
db.session.commit()
Basically I would like to do what's described here:
Another disadvantage is that Flask-SQLAlchemy makes using the database
outside of a Flask context difficult. This is because, with
FLask-SQLAlchemy, the database connection, models, and app are all
located within the app.py file. Having models within the app file, we
have limited ability to interact with the database outside of the app.
This makes loading data outside of your app difficult. Additionally,
this makes it hard to retrieve data outside of the Flask context.
Well, once you initialize the app, Flask spines a server (either development or production, whichever you set), so if you would like to add data to a database with Flask-SQLAlchemy without the Flask app running, you would better use the flask shell command which runs in the context of the current app, then you could add your data.
But first, it would be better is you set up your app as the following so we could directly import stuff like db, auth, etc:
...
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_app():
app = Flask(__name__)
db.init_app(app)
return app
In the root of your project, type in the terminal the following command
flask shell
Now that you have a shell running in the context of the current app but not the server not running:
from app import db
from model import Machine # class Machine(db.Model)
p = Machine(name='something')
# now I need the initialized db from somewhere
db.session.add(p)
db.session.commit()
From the wonderful tutorial...
https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database
Define something like this...
from app import app, db
from app.models import User, Post
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Post': Post}
And then...
(venv) $ flask shell
>>> db
<SQLAlchemy engine=sqlite:////Users/migu7781/Documents/dev/flask/microblog2/app.db>
>>> User
<class 'app.models.User'>
>>> Post
<class 'app.models.Post'>

flask init_db in app_context vs not? what is the difference?

I have multiple apps and use flask_sqlalchemy with the style below:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app(app)
return app
However, in the test, all the app linked to the same database.
after I switch to the following style. Every app can linked to its own database.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
with app.app_context():
db.init_app(app)
return app
I did not understand why? If the second case is better, why it is not in the official doc?
credit: I copied the second style from https://hackingandslacking.com/demystifying-flasks-application-context-c7bd31a53817
Each app you create has it is own context, using the below block of code:
with app.app_context():
db.init_app(app)
means that you initialize those instances to that app context only and trying to access those instances somewhere else will result in the below error.
RunTimeError: Working outside of application context.
You can read more about Flask app context here

Making use of CherryPy as webserver for flask application

I have a simple flask application that works really well. I've been developing it separately from the main desktop application, I want to "plugin" the flask application into the main application. I also want to use cherrypy as the webserver as the default webserver that comes with flask is not production ready. I am not sure how to get both these to work together. My flask application code looks like this
from flask import Flask, render_template,send_from_directory
from scripts_data import test_data
from schedule_data import scheduledata
import os
app=Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/scripts')
def scripts():
test_data=t_data()
return render_template('scripts.html',data_scripts=test_data)
#app.route('/sch')
def schedules():
data_schedule=s_data()
return render_template('schedules.html',table_data=data_schedule)
if __name__=='__main__':
app.run(debug=True)
so obviously as I want to integrate into the main application I can't use app.run. Its not clear how to swap out the flask webserver for the Cherrypy Webserver
I have seen the following
from flask import Flask
import cherrypy
app = Flask(__name__)
app.debug = True
Class setup_webserver(object):
#app.route("/")
def hello():
return "Hello World!"
def run_server():
# Mount the WSGI callable object (app) on the root directory
cherrypy.tree.graft(app, '/')
# Set the configuration of the web server
cherrypy.config.update({
'engine.autoreload_on': True,
'log.screen': True,
'server.socket_port': 5000,
'server.socket_host': '0.0.0.0'
})
# Start the CherryPy WSGI web server
cherrypy.engine.start()
cherrypy.engine.block()
Class start_it_all(object)
import setup_webserver
setup_webserver.run_server()
But when I start the webserver and go to the site (0.0.0.0:5000) I get a 404?
I don't get the 404 when its just flask on its own. All I want to do is swap out the flask built-in webserver for the cherrpy webserver. I don't want to use cherrypy for anything else, as Flask will be the framework
Any suggestions? I'm on Windows and using python 2.7

using flask-migrate with flask-script and application factory

I'm building flask application and decided to try application factory approach this time, but got into trouble with flask-migrate and can't figure out simple solution.
Please note that I want to pass config location as an option to the script
manage.py:
manager = Manager(create_app)
manager.add_option("-c", "--config", dest="config_module", required=False)
then i need to create migrate instance and add command to the manager:
with manager.app.app_context():
migrate = Migrate(current_app, db)
manager.add_command('db', MigrateCommand)
but app instance is not created yet, so it fails
I know I can pass config in environment variable and create application before creating manager instance, but how to do it using manager options?
When you use a --config option you have to use an application factory function as you know, as this function gets the config as an argument and that allows you to create the app with the right configuration.
Since you have an app factory, you have to use the deferred initialization for all your extensions. You instantiate your extensions without passing any arguments, and then in your app factory function after you create the application, you call init_app on all your extensions, passing the app and db now that you have them.
The MigrateCommand is completely separate from this, you can add that to the Manager without having app and db instances created.
Example:
manage.py:
from app import create_app
from flask_migrate import MigrateCommand, Manager
manager = Manager(create_app)
manager.add_option("-c", "--config", dest="config_module", required=False)
manager.add_command('db', MigrateCommand)
app.py (or however your app factory module is called)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy()
migrate = Migrate()
def create_app(config):
app = Flask(__name__)
# apply configuration
# ...
# initialize extensions
db.init_app(app)
migrate.init_app(app, db)
return app