I am working on a small rest api in flask. Api has route that registers a request and spawn separate thread to run in background. Here is the code:
def dostuff(scriptname):
new_thread = threading.Thread(target=executescript,args=(scriptname,))
new_thread.start()
Thread starts but it errors out when I try to insert into db from executescript function. It complains about db object not registered with the app.
I am dynamically creating my app (with api as Blueprint).
Here is the structure of the app
-run.py ## runner script
-config
-development.py
-prod.py
-app
-__init__.py
- auth.py
- api_v1
- __init__.py
- routes.py
- models.py
here is my runner script run.py
:
from app import create_app, db
if __name__ == '__main__':
app = create_app(os.environ.get('FLASK_CONFIG', 'development'))
with app.app_context():
db.create_all()
app.run()
Here is the code from app/__init__.py
which creates the app:
from flask import Flask, jsonify, g
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config_name):
"""Create an application instance."""
app = Flask(__name__)
# apply configuration
cfg = os.path.join(os.getcwd(), 'config', config_name + '.py')
app.config.from_pyfile(cfg)
# initialize extensions
db.init_app(app)
# register blueprints
from .api_v1 import api as api_blueprint
app.register_blueprint(api_blueprint, url_prefix='/api/')
return app
All I need to know is how do I extend app context in routes.py
. I can not import app there directly and if I do the following, I get RuntimeError: working outside of application context
def executescript(scriptname):
with current_app.app_context():
test_run = Testrun(pid=989, exit_status=988,comments="Test TestStarted")
db.session.add(test_run)
db.session.commit()
Flask-SQLAlchemy is a Flask extension that makes using SQLAlchemy with Flask easier, providing you tools and methods to interact with your database in your Flask applications through SQLAlchemy. In this tutorial, you'll build a small student management system that demonstrates how to use the Flask-SQLAlchemy extension.
The application context is a good place to store common data during a request or CLI command. Flask provides the g object for this purpose. It is a simple namespace object that has the same lifetime as an application context.
One of which is that Flask-SQLAlchemy has its own API. This adds complexity by having its different methods for ORM queries and models separate from the SQLAlchemy API. Another disadvantage is that Flask-SQLAlchemy makes using the database outside of a Flask context difficult.
This does not completely answer your question, because it does not remove Flask dependency, but you can use SqlAlchemy in scripts and tests by just not running the Flask app. One difficulty you may encounter is the requirement of using db.
You're running a background task in a different thread that doesn't have the application context. You should pass the app object to the background worker. Miguel Grinberg gives an example of this here:
from threading import Thread
from app import app
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
thr = Thread(target=send_async_email, args=[app, msg])
thr.start()
Alternatively (and probably the best solution) would be to actually set up a thread-local scoped SQLAlchemy session instead of relying on Flask-SQLAlchemy's request context.
>>> from sqlalchemy.orm import scoped_session
>>> from sqlalchemy.orm import sessionmaker
>>> session_factory = sessionmaker(bind=some_engine)
>>> Session = scoped_session(session_factory)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With