I created two databases using the following code with python+flask+sqlalchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///C:\\Users\\dmac'
app.config['SQLALCHEMY_BINDS'] = {
'user': 'sqlite:///C:\\Users\\dmac\\user.db',
'stock': 'sqlite:///C:\\Users\\dmac\\price.db'
}
db = SQLAlchemy(app)
migrate = Migrate(app, db, render_as_batch = True)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
I run the following script:
python app.py db init--multi
python app.py migrate
I get the following error: sqlalchemy.exc.OperationalError:(sqlite3.OperationalError) unable to open database file (Background on this error at: http://sqlalche.me/e/e3q8)
I have looked and tried different solutions posted, but I still get the same errors. Any helps would be appreciative. Thanks
I think the problem is that you're pointing SQLALCHEMY_DATABASE_URI to a folder instead of a database. So SQLAlchemy tries to open the dmac folder as if it were a database which it isn't and fails.
https://flask-sqlalchemy.palletsprojects.com/en/2.x/binds/
Related
I created a Flask app with SQLAlchemy.
I initialised the database in app.py but I want to use it in another file: otherfile.py.
app.py
app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///my_database'
db = SQLAlchemy(app)
print("TEST")
otherfile.py
from app import db
print(db)
But I get the error.
ImportError: cannot import name 'db'
Basically, I am doing this because I do not want to write the SQLAlchemy logic in app.py but I want to keep it in another file.
In addition, I just want the variable db to be exported. I do not want that when I run otherfile.py, this runs also print("TEST") which is in app.py
I looked at these answer with little luck:
How to share the global app object in flask?
Split Python Flask app into multiple files
How to divide flask app into multiple py files?
The SQLAlchemy class doesn't need to receive the app param on its initialization. So what you can do is create the db object in your otherfile.py and import it in app.py, where you can pass it the app object with SQLAlchemy.init_app().
app.py
from flask import Flask
from otherfile import db
app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///my_database'
db.init_app(app)
otherfile.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
I have the following project structure:
project/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
db = SQLAlchemy()
migrate = Migrate()
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
db.init_app(app)
migrate.init_app(app, db)
return app
run.py
from project import create_app
app = create_app()
if __name__ == "__main__":
app.run()
manage.py
from flask_script import Manager
from flask_migrate import MigrateCommand
from project.models import *
from project import create_app
manager = Manager(create_app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
Yet when I run the following commands, Flask-Migrate is not detecting any tables to be added.
python manage.py db init
Which outputs:
Creating directory $HOME/Project/migrations ... done
Creating directory $HOME/Project/migrations/versions ... done
Generating $HOME/Project/migrations/script.py.mako ... done
Generating $HOME/Project/migrations/env.py ... done
Generating $HOME/Project/migrations/README ... done
Generating $HOME/Project/migrations/alembic.ini ... done
Please edit configuration/connection/logging settings in
'$HOME/Project/migrations/alembic.ini' before proceeding.
and
python manage.py db migrate
Which only outputs:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
Why is Flask-Migrate with Alembic not detecting the Models and therefore creating the tables? Here's what I've tried:
Deleting the database, starting from nothing
Creating a custom db class inside the manage.py file, doesn't detect that
Googling every answer to this problem, found lots of similar questions but none of their solutions worked for me.
EDIT:
Here is an example of the models.py file
from flask import current_app
from project import db
from flask_login import UserMixin
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
The solution was to import the models in the __init__.py file like so:
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
from project import models
db.init_app(app)
migrate.init_app(app, db)
return app
I had the same issue. The solution is pretty same as #joe's
In routes file
from models import User
api_user = Namespace('user', description='user related operations')
In project/__init__.py
def create_app():
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
from project import models
db.init_app(app)
migrate.init_app(app, db)
blueprint = Blueprint('api', __name__, url_prefix=url_prefix)
api = Api(blueprint, doc='/documentation') # ,doc=False
app.register_blueprint(blueprint)
api.add_namespace(api_user)
return app
when adding api_user namespace in create_app flask_migrate detected models
Here's my file structure:
/
/apitestproject
/models
__init__.py
users.py
items.py
/resources
__init__.py
users.py
items.py
__init__.py
index.py
.deployment
deploy.cmd
requirements.txt
run_waitress_server.py
runserver.py
web.config
Inside my main __init__.py file I have:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
POSTGRES = {
'user': 'admin_user#pracap',
'pw': 'the_password',
'db': 'apitest',
'host': 'pracap.postgres.database.azure.com',
'port': '5432',
}
URL = 'postgresql://{}:{}#{}:{}/{}'.format(POSTGRES['user'], POSTGRES['pw'], POSTGRES['host'], POSTGRES['port'], POSTGRES['db'])
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = URL
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
import apitestproject.index
In my index.py file I have:
from flask import Flask
from flask_restful import Api
from apitestproject import app, db
#app.before_first_request
def create_tables():
db.create_all()
#app.route('/')
#app.route('/home')
def home():
return "I'm the default route"
And in my /models/users.py file i have:
from apitestproject import db
class UserModel(db.Model):
__tablename__ = 'users'
id = db.column(db.string, primary_key=True)
name = db.column(db.string(50))
address = db.column(db.string(144))
salary = db.column(db.numeric(12, 2))
position = db.column(db.string(50))
password = db.column(db.string(50))
The console is not throwing any errors and I can run everything right without even a single hint of an error. But the tables are not created. Any idea what I might be doing wrong? I've been working with flask/sqlalchemy for just over a month now and I'm starting to work with DB's.
Any help would be appreciated!
I think you will need to work with flask-migrate as a good alternative :
just find this tutorial about it :
a short descrition about it is here :
Migrations allow us to manage changes we make to the models, and
propagate these changes in the database. For example, if later on we
make a change to a field in one of the models, all we will need to do
is create and apply a migration, and the database will reflect the
change.
after installing it via
pip install flask-migrate
edit your init.py like this :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
POSTGRES = {
'user': 'admin_user#pracap',
'pw': 'the_password',
'db': 'apitest',
'host': 'pracap.postgres.database.azure.com',
'port': '5432',
}
URL = 'postgresql://{}:{}#{}:{}/{}'.format(POSTGRES['user'], POSTGRES['pw'], POSTGRES['host'], POSTGRES['port'], POSTGRES['db'])
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = URL
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db)
import apitestproject.index
and then edit your index.py by removing the db creatation you will do it via command line .
from flask import Flask
from flask_restful import Api
from apitestproject import app, db
#app.route('/')
#app.route('/home')
def home():
return "I'm the default route"
after that go to your application directory and export the flask app and what are the run script of your app?? :
in cmd do this :
export FLASK_APP=your_runScript.py
and then the 2 following commands to migrate the db :
flask db init
to create the migration folder
and :
flask db migrate
to create the first migration
and :
flask db upgrade
to upgrade changes to the db
find more here about the flask-migrate package
Here is my migration file :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
import models
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + 'C:\\flaskDB\\commBorn3.db'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
I ran the standard commands :
python app.py db init
python app.py db migrate
python app.py db upgrade
The resulting database was a file of the same name with about the same size in kb but only one table, "alembic_version" which had nothing in it. I tried to downgrade and found all my tables returned but they were empty. What did I do wrong? Where is all the data hiding (same kb size of file)?
You should always check the migration file in migrations/versions created after db migrate, and execute db upgrade only when everything looks alright.
The problem is that in models.py you import a db = SQLAlchemy(app) instance from your "normal" app, not from the migration script. So in the migration script you actually don't define any model, and this is why it deletes all your tables in the database.
The solution is easy: just use the migration script's app context when you import the models:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + 'C:\\flaskDB\\commBorn3.db'
db = SQLAlchemy(app)
# Import database models with app context
with app.app_context():
from models import *
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
I'm trying to implement the Flask manager for SQLalchemy.
When I run python run.py db migrate then python run.py db upgrade, my tables aren't affected. I just removed a field from my models.py file that should be removed from the table.
Here are my files :
root/run.py :
#!flask/bin/python
import sys
sys.path.append("/app")
from app import app
app.run(debug = True)
root/app/__init__.py :
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand
from app.database import db, db_session, init_db
app = Flask(__name__)
app.config.from_object('settings')
init_db()
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
from catalog.views import catalog
app.register_blueprint(catalog)
root/app/database.py :
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('mysql://root:root#127.0.0.1/mydb', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
db = declarative_base()
db.query = db_session.query_property()
def init_db():
import app.models
db.metadata.create_all(bind=engine)
I think I'm doing it wrong with the manager.run() but I'm not clearly understanding how to run it.
EDIT :
I finally made more simple database settings after iurisilvio's advice :
root/app/__init__.py :
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate
app = Flask(__name__)
app.config.from_object('settings')
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root#127.0.0.1/mydb'
db = SQLAlchemy()
db.app = app
db.init_app(app)
migrate = Migrate(app, db)
manager = Manager(app)
from catalogue.views import catalogue
app.register_blueprint(catalogue)
root/run.py :
#!flask/bin/python
import sys
sys.path.append("/app")
from app import app, manager
from flask.ext.migrate import MigrateCommand
manager.add_command('db', MigrateCommand)
app.debug = True
manager.run()
Now it works pretty fine !
Flask-Migrate works with the Flask-SQLAlchemy session. You are creating your session with raw sqlalchemy.
I don't know if it is possible at all. You have to change your database.py to work with Flask-SQLAlchemy.