问题
I'm using Alembic to handle migrations for Flask. alembic revision --autogenerate
should, in theory, autogenerate a migration based on changes in my database. However, Alembic is simply generating a blank migration with the above command.
There's a question very similar to this one, where the issue was that the proper models weren't being imported. However, I have imported the models from my Flask app, as shown in env.py
:
...
# import settings from Flask
alembic_config = config.get_section(config.config_ini_section)
from start import app
from models import User, Item, Recipient # models are imported here from models.py
alembic_config['sqlalchemy.url'] = app.config['SQLALCHEMY_DATABASE_URI']
engine = engine_from_config(
alembic_config, # config.get_section(config.config_ini_section)
prefix='sqlalchemy.',
poolclass=pool.NullPool)
...
As well as imported db metadata in env.py
('start' is the name of my Flask app's main file):
...
from start import db
target_metadata = db.metadata
...
Running alembic revision --autogenerate -m "initial_rev"
then generates an empty migration, although my Flask app would beg to differ:
"""initial_rev
Revision ID: 45296fd29540
Revises: None
Create Date: 2013-06-19 17:32:38.392268
"""
# revision identifiers, used by Alembic.
revision = '45296fd29540'
down_revision = None
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
Edit
Here is a gist that shows the file structure for my app, as well as some additional code. It seems the issue is that Alembic does not like having the db imported from database.py
without being initialized first in __init__.py
. However, this is not possible when blueprints are used (because of cyclical imports), explained in this SO answer: https://stackoverflow.com/a/9695045/353878.
So the question is, how can Alembic be used when Flask blueprints are used as well?
Edit #2
I even tried printing db.metadata.sorted_tables
, to make sure the database metadata was being imported correctly. Sure enough, the whole database schema was piped to the terminal. So why is Alembic generating blank upgrade/downgrade functions?
Edit #3
I've concluded that the issue has something to do with the differences of db.init_app(app)
and db = SQLAlchemy(app)
, but I'm not quite sure what is causing the issue. To test this theory, I replaced from database import db
in env.py
to be db = SQLAlchemy(app)
. Probably a bad idea, but I wanted to see what would happen for debugging purposes.
Alembic autogenerated and filled the upgrade() and downgrade() methods- except they were reversed! upgrade()
dropped all three of my tables, while downgrade()
created them with all the proper columns and metadata. I have no idea why this is, but I hope it is helpful to people trying to figure out this problem.
回答1:
Here is how I use Alembic with Flask and blueprints.
https://github.com/davidism/basic_flask
I use the application factory pattern and call db.init_app
within that. After db = SQLAlchemy()
I import all models that will subclass db.Model
so that db.metadata
is aware of them; note this is not done in the create_app
factory, but just inline during module init.
When running alembic
, the project folder is not included in sys.path
so I set that up. Then I create an app from the factory and set sqlalchemy.url
from its configuration. Also, I import db
and set target_metadata = db.metadata
.
This setup works for me all the time, no matter the project structure. I included a very basic set of user models and a very dumb view in a subpackage with a blueprint. Just make sure to load the relavent models in load_models
, import the views after defining the blueprint, and import the blueprints in init_views
.
来源:https://stackoverflow.com/questions/17201800/alembic-autogenerates-empty-flask-sqlalchemy-migrations