26

I'm using Flask with Flask-SQLAlchemy and Flask-Migrate to create an application, however when I try to create a migration nothing happens.

I've created two tables in app/models.py:

from flask import current_app
from . import db

class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, nullable=False)
    password_hash = db.Column(db.String(128))

    def __init__(self, **kwargs):
        super(Student, self).__init__(**kwargs)

    def __repr__(self):
        return '<Tutor {}>' % self.id

class Tutor(db.Model):
    __tablename__ = 'tutors'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))

    def __init__(self, **kwargs):
        super(Tutor, self).__init__(**kwargs)
    def __repr__(self):
        return '<Student %r>' % self.id

Then I also have app/__init__.py with the following code:

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

#from .models import User, Task, Project, UserProject

from config import config

bootstrap = Bootstrap()
db = SQLAlchemy()
migrate = Migrate()

def create_app(config_name='default'):
    #print config_name.name
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    bootstrap.init_app(app)
    db.init_app(app)
    migrate.init_app(app, db)

    ## Register the main blueprint for main app functionality
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    return app

and app.py:

import os
from app import create_app, db
from app.models import Tutor, Student

app = create_app('default')

@app.shell_context_processor
def make_shell_context():
    return dict(db=db, Tutor=Tutor, Student=Student)

I can run flask db init with no problem and it creates the migrations directory and all necessary files with the following output:

Creating directory /Users/Jasmine/projects/flask/flask-tutoring/migrations ... done
Creating directory /Users/Jasmine/projects/flask/flask-tutoring/migrations/versions ... done
Generating /Users/Jasmine/projects/flask/flask-tutoring/migrations/script.py.mako ... done
Generating /Users/Jasmine/projects/flask/flask-tutoring/migrations/env.py ... done
Generating /Users/Jasmine/projects/flask/flask-tutoring/migrations/README ... done
Generating /Users/Jasmine/projects/flask/flask-tutoring/migrations/alembic.ini ... done
Please edit configuration/connection/logging settings in '/Users/Jasmine/projects/flask/flask-tutoring/migrations/alembic.ini' before proceeding.

but when I try and run flask db migrate alembic can't detect that I've got tables in app/models.py. I get the following output:

INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.env] No changes in schema detected.

There is no migration script created, its as though models.py doesn't exist.

Apologies if this is a repeated question, but I can't find another example where its the first migration that fails and no migration script at all is created.

I've tried checking if there is already a table created somewhere by running db.drop_all() in the shell but that doesn't seem to be the problem.

UPDATE

I figured out a way to solve this on my own but would like a better understanding of why this worked.

I re-named app.py to flasktutor.py and re-ran export FLASK_APP='flasktutor.py'. Subsequently the migration worked perfectly.

Please could someone explain why when the file was called app.py and I used export FLASK_APP='app.py' the migration did not register changes to the schema.

DINA TAKLIT
  • 7,074
  • 10
  • 69
  • 74
J Finer
  • 389
  • 1
  • 3
  • 10
  • There's got to be something else that you changed. I have an application called app.py that I use to test Flask-Migrate and that works perfectly well. If you have a complete example that shows this problem it would be useful if you can share it. – Miguel Grinberg Aug 11 '18 at 22:13
  • I have the same problem but my file's name is run.py. I changed it to app.py then to phoenix.py and still the same issue. Debugging the application on this line `app.config.from_object(app_config[config_name])` I uncovered that the reference to config_name is throwing the same error when I run the app. `KeyError: `. – Isomorph Sep 11 '18 at 04:58
  • This was an issue I had, thanks for this, it is to do with flask mixing up a package and a module import of the same name at different points – 13ros27 May 16 '20 at 11:28

10 Answers10

22

I encountered this problem and solved it by importing my models at env.py in the migrations folder right after the following comments

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata

from app.models import Student, Tutor
Swaleh Matongwa
  • 698
  • 9
  • 16
16

Pls make sure that you already import your models (Tutor, Student, ...) before your migrate.init_app(app, db)

enpith
  • 1,540
  • 2
  • 10
  • 11
11

This is how I solved the problem in my case:

  1. Import the Migrate model: from flask_migrate import Migrate
  2. Initiate Migrate class: migrate = Migrate(app, db)
  3. Comment db.create_all()
  4. Drop your database now => DROP DATABASE db_name;
  5. Create it again => CREATE DATABSE db_name OWNER owner_name;
  6. Export you flask entry file => export FLASK_APP=name_app.py
  7. Run flask db migrate

Note: The 6th step should be used in case you get this error:

Error: Could not locate a Flask application

Hope this will help someone.

Paul P
  • 3,346
  • 2
  • 12
  • 26
DINA TAKLIT
  • 7,074
  • 10
  • 69
  • 74
11

I just ran into the same issue, following Miguel's great tutorial, and the hints here were very helpful!

My solution - which doesn't require "hacking" env.py - is to simply add

from app import models

to __init__.py.

If you have a different project layout you might need to adapt the import but it seems like you need to make sure that models gets imported properly for flask db migrate to work.

Paul P
  • 3,346
  • 2
  • 12
  • 26
  • Perfect! "Imports" were the culprits here. Did not import models before instantiating the Migrate() earlier. – P0intMaN Feb 21 '22 at 08:01
  • 1
    I was following the same (amazing) tutorial. I'd changed the module name to "bloggy" in order to disambiguate `app`. So my import is `from bloggy import models` and viola table has been created. – Boyd Hemphill May 21 '22 at 18:45
6

Well, I encountered the same problem following Miguel Grinberg tutorial.

Previously I created the tables using the shell calling

db.create_all()

So, I thougth to drop the tables

db.drop_all()

and trying the migrate command again, it worked as expected:

Roberto@MyPC MINGW64 /e/Projects/Flask/flasky ((5c))
$ flask db migrate -m "initial migration - Role Users"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'roles'
INFO  [alembic.autogenerate.compare] Detected added table 'users'
INFO  [alembic.autogenerate.compare] Detected added index 'ix_users_username' on '['username']'
Generating E:\Projects\Flask\flasky\migrations\versions\4de323c9c089_initial_migration_role_users.py ... done

After that, I used flask-migrate to re-create the tables

$ flask db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> b641ee80a60d, initial migration - Role Users
RobertoW
  • 61
  • 1
  • 2
2

I encountered the same problem following Miguel Grinberg tutorial. I solved this my adding

from app.models import  User, Post

to migrations/env.py

Jonathan Chow
  • 1,207
  • 1
  • 9
  • 11
2

The flask-migrate works after you change your table schema.

Such as, before:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

class Test(db.Model):
    content = db.Column(db.String(60))

and then you change your Test schema, like:

class Test(db.Model):
    content = db.Column(db.String(60))
    add = db.Column(db.String(60))

Now, you can use flask db migrate -m "migrate test" to work.

You will get migrate version information.

ZealYoung
  • 39
  • 1
  • 5
2

This worked for me:

In migrations/env.py, import your models

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from app.models import * # <= Add this line
from flask import current_app
Thang Ngo
  • 21
  • 2
0

You can point to empty database only to create migration file, then return back to upgrade your real database.

tabebqena
  • 1,204
  • 1
  • 13
  • 23
0

After some time trying to fix it and reading about it, I just deleted the migrations directory (folder) and the app.db. Then ran again:

  1. "flask db init"
  2. "flask db migrate"
  3. "flask db upgrade"

This re-generate the directories and all working fine now.

If you want to improve your migration script, this link to an upgrade from Miguel, can be useful: https://www.youtube.com/watch?v=wpRVZFwsD70&feature=emb_logo