I'm currently trying to piece together a small Flask application. This is my structure.
run.py
application
__init__.py
database.py
models.py
views.py
database.py
contains just the SQLAlchemy object:
db = SQLAlchemy()
I then import this into my models.py
to create my models. Lastly, inside __init__.py
I import db
from database.py
and do:
from .database import db
from flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///application.db'
db.init_app(app)
db.create_all()
However, I cannot create the tables from the models it appears. If I remove db.create_all()
. The application will run with no problems, but obviously the database is not created. When db.create_all()
is present I am given 'RuntimeError: application not registered on db instance and no application bound to current context'.
I'm honestly confused, as before I was having issues just starting the application without creating the database, but moving db
to it's own file seems to somehow have corrected that issue. Now, the only issue remains is actually creating the database.
Can anyone tell me what might be the problem? I'm genuinely stumped.
The answer is here: http://flask-sqlalchemy.pocoo.org/latest/api/#configuration
See the part about:
The difference between the two is that in the first case methods like create_all() and drop_all() will work all the time but in the second case a flask.Flask.request_context() has to exist.
There's more information here: http://flask-sqlalchemy.pocoo.org/latest/contexts/
If all that is confusing (it probably is, since it's talking about a fairly advanced feature of Flask), the short short version is db.init_app(app)
changes the app
object, but it doesn't change anything in the db
object. It's on purpose because there might be more than one app
flying around, and db
might have to talk to all of them. (I said it was an advanced feature.)
So when you call db.create_all()
without having a request live (which creates a global that has the currently running app
) it doesn't know what to connect to, and bombs. That's what the error means.
In your case, I would put the SQLAlchemy call back in __init__.py
and pass app
to it, that's the easiest way:
db = SQLAlchemy(app)
Or keep things as they are, and run the setup before the first request:
@app.before_first_request
def create_database():
db.create_all()
I hope that helps! Let me know if you run into any more problems.
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