Heroku, Flask, PostgreSQL - Problem linking database [duplicate] - python

I recently updated Flask-SQLAlchemy, and now db.create_all is raising RuntimeError: working outside of application context. How do I call create_all?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.create_all()
This raises the following error:
Traceback (most recent call last):
File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
db.create_all()
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
self._call_for_binds(bind_key, "create_all")
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
engine = self.engines[key]
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
app = current_app._get_current_object() # type: ignore[attr-defined]
File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.

As of Flask-SQLAlchemy 3.0, all access to db.engine (and db.session) requires an active Flask application context. db.create_all uses db.engine, so it requires an app context.
with app.app_context():
db.create_all()
When Flask handles requests or runs CLI commands, a context is automatically pushed. You only need to push one manually outside of those situations, such as while setting up the app.
Instead of calling create_all in your code, you can also call it manually in the shell. Use flask shell to start a Python shell that already has an app context and the db object imported.
$ flask shell
>>> db.create_all()
Or push a context manually if using a plain python shell.
$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()

Here's an example.py that configures a SQLite database, a model, then creates the database. The with app.app_context() line around db.create_all() is what's needed to avoid the context error.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.String)
with app.app_context():
db.create_all()
Run the development server with this command, and the database will be created if it doesn't exist.
$ flask -A example.py --debug run

If you're using a python shell instead of flask shell, you can push a context manually. flask shell will handle that for you.
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Learn more about the application context in the Flask docs or this video.

Related

I keep getting Internal server error no matter how many times I terminate the ports using Taskkill /PID [duplicate]

I recently updated Flask-SQLAlchemy, and now db.create_all is raising RuntimeError: working outside of application context. How do I call create_all?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.create_all()
This raises the following error:
Traceback (most recent call last):
File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
db.create_all()
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
self._call_for_binds(bind_key, "create_all")
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
engine = self.engines[key]
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
app = current_app._get_current_object() # type: ignore[attr-defined]
File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
As of Flask-SQLAlchemy 3.0, all access to db.engine (and db.session) requires an active Flask application context. db.create_all uses db.engine, so it requires an app context.
with app.app_context():
db.create_all()
When Flask handles requests or runs CLI commands, a context is automatically pushed. You only need to push one manually outside of those situations, such as while setting up the app.
Instead of calling create_all in your code, you can also call it manually in the shell. Use flask shell to start a Python shell that already has an app context and the db object imported.
$ flask shell
>>> db.create_all()
Or push a context manually if using a plain python shell.
$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Here's an example.py that configures a SQLite database, a model, then creates the database. The with app.app_context() line around db.create_all() is what's needed to avoid the context error.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.String)
with app.app_context():
db.create_all()
Run the development server with this command, and the database will be created if it doesn't exist.
$ flask -A example.py --debug run
If you're using a python shell instead of flask shell, you can push a context manually. flask shell will handle that for you.
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Learn more about the application context in the Flask docs or this video.

Flask problem creating table db.create_all() [duplicate]

I recently updated Flask-SQLAlchemy, and now db.create_all is raising RuntimeError: working outside of application context. How do I call create_all?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.create_all()
This raises the following error:
Traceback (most recent call last):
File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
db.create_all()
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
self._call_for_binds(bind_key, "create_all")
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
engine = self.engines[key]
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
app = current_app._get_current_object() # type: ignore[attr-defined]
File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
As of Flask-SQLAlchemy 3.0, all access to db.engine (and db.session) requires an active Flask application context. db.create_all uses db.engine, so it requires an app context.
with app.app_context():
db.create_all()
When Flask handles requests or runs CLI commands, a context is automatically pushed. You only need to push one manually outside of those situations, such as while setting up the app.
Instead of calling create_all in your code, you can also call it manually in the shell. Use flask shell to start a Python shell that already has an app context and the db object imported.
$ flask shell
>>> db.create_all()
Or push a context manually if using a plain python shell.
$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Here's an example.py that configures a SQLite database, a model, then creates the database. The with app.app_context() line around db.create_all() is what's needed to avoid the context error.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.String)
with app.app_context():
db.create_all()
Run the development server with this command, and the database will be created if it doesn't exist.
$ flask -A example.py --debug run
If you're using a python shell instead of flask shell, you can push a context manually. flask shell will handle that for you.
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Learn more about the application context in the Flask docs or this video.

Flask-SQLAlchemy db.create_all() raises RuntimeError working outside of application context

I recently updated Flask-SQLAlchemy, and now db.create_all is raising RuntimeError: working outside of application context. How do I call create_all?
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
db.create_all()
This raises the following error:
Traceback (most recent call last):
File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
db.create_all()
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
self._call_for_binds(bind_key, "create_all")
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
engine = self.engines[key]
File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
app = current_app._get_current_object() # type: ignore[attr-defined]
File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
As of Flask-SQLAlchemy 3.0, all access to db.engine (and db.session) requires an active Flask application context. db.create_all uses db.engine, so it requires an app context.
with app.app_context():
db.create_all()
When Flask handles requests or runs CLI commands, a context is automatically pushed. You only need to push one manually outside of those situations, such as while setting up the app.
Instead of calling create_all in your code, you can also call it manually in the shell. Use flask shell to start a Python shell that already has an app context and the db object imported.
$ flask shell
>>> db.create_all()
Or push a context manually if using a plain python shell.
$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Here's an example.py that configures a SQLite database, a model, then creates the database. The with app.app_context() line around db.create_all() is what's needed to avoid the context error.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
body = db.Column(db.String)
with app.app_context():
db.create_all()
Run the development server with this command, and the database will be created if it doesn't exist.
$ flask -A example.py --debug run
If you're using a python shell instead of flask shell, you can push a context manually. flask shell will handle that for you.
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()
Learn more about the application context in the Flask docs or this video.

Stream data to database for Flask app to consume [duplicate]

This question already has answers here:
flask make_response with large files
(2 answers)
Closed 3 years ago.
I'm fairly new to this task so please help me identify the concepts I'm missing.
I'm trying to stream data from an API to my SQLite db and let a Flask app consume the data. I defined the models in models.py like this
# models.py
import os
from flask_sqlalchemy import SQLAlchemy
# Create sqlite db
db = SQLAlchemy()
class MyDataModel(db.Model):
# Manual table name choice
__tablename__ = 'table1'
id = db.Column(db.Integer, primary_key=True)
created_at = db.Column(db.Text)
text = db.Column(db.Text)
def __init__(self, created_at, text):
self.created_at = created_at
self.text = text
def __repr__(self):
return f"Data: {self.text} ... created at {self.created_at}"
In app.py I have a simple view function that counts the rows and return a Server Sent Event to the frontend for realtime tracking.
# app.py
import os
import time
from flask import Flask, render_template, url_for, redirect, Response
from flask_migrate import Migrate
from models import db, MyDataModel
from settings import *
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
Migrate(app, db)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/getcount')
def getcount():
def count_stream():
count = db.session.query(MyDataModel).count()
while True:
yield f"data:{str(count)}\n\n"
time.sleep(0.5)
return Response(count_stream(), mimetype='text/event-stream')
if __name__ == "__main__":
app.run(debug=True, port=PORT)
Now I have another python script stream_to_db.py that gets data from an API as a stream, approximately like this
# stream_to_db.py
import logging
import os
from models import db, MyDataModel
from settings import *
from SomeExternalAPI import SomeAPI
def stream_to_db():
api = SomeAPI(
API_KEY, API_SECRET_KEY, ACCESS_TOKEN, ACCESS_TOKEN_SECRET
)
r = api.request()
for item in r:
created_at, text = item['created_at'], item['text']
logging.info(text)
datum = MyDataModel(created_at, text)
db.session.add(datum)
db.session.commit()
# Stream data to sqlite
stream_to_db()
When I try to run this python stream_to_db.py I get error
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
I looked at the documentation of application context but am still confused. Say I go without SQLAlchemy and use Python and SQL directly for data insertion, this stream_to_db.py script should be independent of the Flask app. But if I still want to leverage SQLAlchemy for its syntax and model definitions from models.py, how should I do it?
Conceptually I feel the streaming to db part is independent of the Flask app and should be a script that's essentially a while True loop and goes forever. The Flask app just reads the db, send data to frontend and does nothing else. I tried put the stream_to_db() function into __main__ in app.py but that doesn't make sense, app.run() and stream_to_db() are both essentially while True loops and can't be put together.
I'm lost and miss key concepts here. Please help and suggest the right way/best practices to do it. I feel this is a really basic task which should have a best practice and a set of dedicated tools already. Thanks in advance!
EDIT
To further experiment, I imported app into stream_to_db.py and added
with app.app_context():
stream_to_db()
Now I can run python stream_to_db.py with no problem, but if I start the Flask app at the same time, I get several
Debugging middleware caught exception in streamed response at a point where response headers were already sent.
and also
Traceback (most recent call last):
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/werkzeug/wsgi.py", line 507, in __next__
return self._next()
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/werkzeug/wrappers/base_response.py", line 45, in _iter_encoded
for item in iterable:
File "/Users/<username>/webapps/<appname>/app.py", line 33, in count_stream
count = db.session.query(CardanoTweet).count()
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/sqlalchemy/orm/scoping.py", line 162, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/sqlalchemy/util/_collections.py", line 1012, in __call__
return self.registry.setdefault(key, self.createfunc())
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 3214, in __call__
return self.class_(**local_kw)
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 136, in __init__
self.app = app = db.get_app()
File "/Users/<username>/webapps/<appname>/venv/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 982, in get_app
'No application found. Either work inside a view function or push'
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
Looks like SQLAlchemy can't find the application. Not sure if it's a problem about the db.init_app(app) in app.py and db = SQLAlchemy() in models.py. I avoided having db = SQLAlchemy(app) in models.py because I can't import app into models for the circular dependency reason.
EDIT2
This time I moved all the code from models.py to app.py and used db = SQLAlchemy(app), removed db.init_app(app), kept the import app to stream_to_db.py and the app context in it, and it worked!
My questions
How to correctly move the model definitions to models.py with no circular dependency?
What's the implication of having app context in stream_to_db.py? If I have gunicorn running many workers, there will essentially be multiple Flask app instances. Would that cause a problem?
EDIT3
Thanks for all the replies. I don't think this is a duplicate to flask make_response with large files.
The problem is not streaming data FROM Flask to the client, it is to stream data from external API to DB, and have Flask consume some statistics from the data in DB. So, I don't see why conceptually the streaming job should be related to Flask at all, they are independent. The problem is that I'm using SQLAlchemy in the streaming job for data model and db transaction, and SQLAlchemy needs Flask app defined. This part is where I get confused about.
What is the right way to write this ever-running background job that streams data to db, with data models defined with SQLAlchemy? Should I strip out the SQLAlchemy code from streaming code and just use SQL, and manually make sure the schema agrees if there are further migration down the road?
Please try following change in models.py where you've created db.
db = SQLAlchemy(app)

When scattering Flask Models, RuntimeError: 'application not registered on db' was raised

I am re-factoring my Flask application by scattering the models, blueprints but I am having a runtime error.
def create_app():
app = flask.Flask("app")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
app.register_blueprint(api)
db.init_app(app)
db.create_all()
return app
I have the following problem(the sample project are hosted here: https://github.com/chfw/sample):
Traceback (most recent call last):
File "application.py", line 17, in <module>
app = create_app()
File "application.py", line 12, in create_app
db.create_all()
File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 856, in create_all
self._execute_for_all_tables(app, bind, 'create_all')
File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 836, in _execute_for_all_tables
app = self.get_app(app)
File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 809, in get_app
raise RuntimeError('application not registered on db
'RuntimeError: application not registered on db
instance and no application bound to current context
I did a research on this topic. The re-factoring is suggested here:
Flask-SQLAlchemy import/context issue
The same problem was raised here:
http://flask.pocoo.org/mailinglist/archive/2010/8/30/sqlalchemy-init-app-problem/#b1c3beb68573efef4d6e571ebc68fa0b
And the above thread(2010) suggested a hack like this:
app.register_blueprint(api)
db.app=app #<------------<<
db.init_app(app)
Did anyone know how to do this properly? How did you solve it?
Thanks
This has to do with Flask's application context. When initialized with db.init_app(app), Flask-SQLAlchemy doesn't know which app is the "current" app (remember, Flask allows for multiple apps in the same interpreter). You could have multiple apps using the same SQLAlchemy instance in the same process, and Flask-SQLAlchemy would need to know which is the "current" one (due to Flask's context local nature of everything).
If you need to do this during runtime, you must explicitly say which app is the "current" app for all calls. You can do this by changing your code to use a with app.app_context() block:
def create_app():
app = flask.Flask("app")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
app.register_blueprint(api)
db.init_app(app)
with app.app_context():
# Extensions like Flask-SQLAlchemy now know what the "current" app
# is while within this block. Therefore, you can now run........
db.create_all()
return app
If you are writing a standalone script that needs the app context, you can push the context at the beginning rather than putting everything in a with block.
create_app().app_context().push()
If you write a command for Flask's cli the command will automatically have access to the context.
Mark's answer was great and it helped me a lot. However, another way to approach this is to run the code that relies on the app context in a function decorated with #app.before_first_request. See http://flask.pocoo.org/docs/0.10/appcontext/ for more information. That's in fact how I ended up doing it, largely because I wanted to be able to call the initialization code outside of flask as well, which I handle this way.
In my case I want to be able to test SQLAlchemy models as plain SQLAlchemy models without Flask-SQLAlchemy, though the db in the code below is simply a (Flask) SQLAlchemy db.
#app.before_first_request
def recreate_test_databases(engine = None, session = None):
if engine == None:
engine = db.engine
if session == None:
session = db.session
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
# Additional setup code

Categories

Resources