Troubles with MySQL, SQLAlchemy, Flask, and flask.ext.script -- create_all() doesn't create tables
Question: I am not able to create tables when I do the following in my virtualenv:

    
    
    (plasma) $ python checkup_web.py shell
    > from app import db 
    > db.create_all()
    

There is no error message thrown at all. Here's the structure of my project:

    
    
    root
    ---app
    ------__init__.py
    ------models.py
    ------[various blueprints]
    ---checkup_web.py
    ---config.py
    

I can include more code if necessary, but I believe that these are the
important files for consideration:

1) checkup_web.py

    
    
    #!/usr/bin/env python
    import os
    from app import create_app, db
    from flask.ext.script import Manager
    
    app = create_app(os.getenv('FLASK_CONFIG') or 'default')
    manager = Manager(app)
    
    
    if __name__ == '__main__':
        manager.run()
    

2) config.py

    
    
    import os
    
    class Config:
        SECRET_KEY = os.environ.get('SECRET_KEY')
    
    
    class DevelopmentConfig(Config):
        DEBUG = True
        SECRET_KEY = os.environ.get('SECRET_KEY') or 't0p s3cr3t'
        SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
            'mysql+pymysql://root:root_password@localhost/checkup_db'
    
    class TestingConfig(Config):
        TESTING = True
        SECRET_KEY = 'secret'
    
    
    class ProductionConfig(Config):
        pass
    
    
    config = {
        'development': DevelopmentConfig,
        'testing': TestingConfig,
        'production': ProductionConfig,
        'default': DevelopmentConfig
    }
    

3) app/__init__.py

    
    
    from flask import Flask
    from flask.ext.sqlalchemy import SQLAlchemy
    from config import config
    
    db = SQLAlchemy()
    
    def create_app(config_name):
        app = Flask(__name__)
        app.config.from_object(config[config_name])
        db.init_app(app)    
    
        from .families import families as families_blueprint
        app.register_blueprint(families_blueprint)
    
        from .patients import patients as patients_blueprint
        app.register_blueprint(patients_blueprint)
    
        from .doctors import doctors as doctors_blueprint
        app.register_blueprint(doctors_blueprint)
    
        from .conversations import conversations as conversations_blueprint
        app.register_blueprint(conversations_blueprint)
    
        from .appointments import appointments as appointments_blueprint
        app.register_blueprint(appointments_blueprint)
    
        return app
    

4) app/models.py (not sure if I'm doing anything wrong here - first time using
SQLAlchemy)

    
    
    from datetime import datetime
    from . import db
    
    family_2_doc = db.Table('family_2_doc',
        db.Column('family_id', db.Integer, db.ForeignKey('families.id')),
        db.Column('doctor_id', db.Integer, db.ForeignKey('users.id'))
    )
    
    patient_2_doc = db.Table('patient_2_doc',
        db.Column('patient_id', db.Integer, db.ForeignKey('users.id')),
        db.Column('doctor_id', db.Integer, db.ForeignKey('users.id'))
    )
    
    class Family(db.Model):
        __tablename__ = 'families'
        id = db.Column(db.Integer, primary_key=True)
        street_address = db.Column(db.String(64))
        city = db.Column(db.String(64))
        zipcode = db.Column(db.String(64))
        country = db.Column(db.String(64))
        phone_number = db.Column(db.String(64))
        stripe_id = db.Column(db.String(64))
        billing_valid = db.Column(db.Boolean)
        num_relationships = db.Column(db.Integer)
        doctors = db.relationship('Doctor', secondary=family_2_doc,
            backref=db.backref('families', lazy='dynamic'), lazy='dynamic')
        patients = db.relationship('Patient', backref='family', lazy='dynamic')
    
    class Clinic(db.Model):
        __tablename__ = 'clinics'
        id = db.Column(db.Integer, primary_key=True)
        street_address = db.Column(db.String(64))
        city = db.Column(db.String(64))
        zipcode = db.Column(db.String(64))
        country = db.Column(db.String(64))
        phone_number = db.Column(db.String(64))
        doctors = db.relationship('Doctor', backref='clinic', lazy='dynamic')
        admins = db.relationship('Admin', backref='clinic', lazy='dynamic')
    
    class User(db.Model):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        email = db.Column(db.String(64), unique=True, index=True)
        first_name = db.Column(db.String(64))
        last_name = db.Column(db.String(64))
        password_hash = db.Column(db.String(128))
        date_joined = db.Column(db.DateTime())
        discriminator = Column('type', String(50))
        __mapper_args__ = {'polymorphic_on': discriminator}
    
    class Patient(User):
        __mapper_args__ = {'polymorphic_identity': 'patient'}
        dob = db.Column(db.String(64))
        relationship_to_creator = db.Column(db.Boolean) # is equal to 'creator' if patient is creator
        is_primary = db.Column(db.Boolean)
        street_address = db.Column(db.String(64))
        city = db.Column(db.String(64))
        zipcode = db.Column(db.String(64))
        country = db.Column(db.String(64))
        phone_number = db.Column(db.String(64))
        profile_pic = db.Column(db.String(64))
        doctors = db.relationship('Doctor', secondary=patient_2_doc,
            backref=db.backref('patients', lazy='dynamic'), lazy='dynamic')
        appointments = db.relationship('Appointment', backref='patient', lazy='dynamic')
    
    class Doctor(User):
        __mapper_args__ = {'polymorphic_identity': 'doctor'}
        practice_street_address = db.Column(db.String(64))
        practice_city = db.Column(db.String(64))
        practice_zipcode = db.Column(db.String(64))
        practice_country = db.Column(db.String(64))
        practice_phone_number = db.Column(db.String(64))
        personal_street_address = db.Column(db.String(64))
        personal_city = db.Column(db.String(64))
        personal_zipcode = db.Column(db.String(64))
        personal_country = db.Column(db.String(64))
        personal_phone_number = db.Column(db.String(64))
        schedule_start = db.Column(db.DateTime())
        schedule_end = db.Column(db.DateTime())
        appointments = db.relationship('Appointment', backref='doctor', lazy='dynamic')    
    
    class Admin(User):
        __mapper_args__ = {'polymorphic_identity': 'admin'}
    
    class Appointment(db.Model):
        __tablename__ = 'appointments'
        is_subscriber = db.Column(db.Boolean)
        start = db.Column(db.DateTime())
        end = db.Column(db.DateTime())
        notes = db.Column(db.Text())
    
    class Message(db.Model):
        __tablename__ = 'messages'
        body = db.Column(db.Text())
        timestamp = db.Column(db.DateTime())
        user1_id = db.Column(db.Integer) # smaller id
        user2_id = db.Column(db.Integer) # larger id
        user_sender_id = db.Column(db.Integer)
        message_number = db.Column(db.Integer)
    
    class Conversation(db.Model):
        __tablename__ = "conversations"
        user1_id = db.Column(db.Integer) # smaller id
        user2_id = db.Column(db.Integer) # larger id
        total_messages = db.Column(db.Integer)
    

Unfortunately despite not throwing any errors, the call to create_all() does
not produce any tables in my mysql database:

    
    
    $ mysql -u root -p
    Password: *********
    
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | channels           |
    | checkup_db         |
    | comments           |
    | media              |
    | mysql              |
    | notifications      |
    | performance_schema |
    | reactions          |
    | sessions           |
    | shares             |
    | sparks             |
    | test               |
    | users              |
    +--------------------+
    14 rows in set (0.01 sec)
    
    mysql> use checkup_db
    Database changed
    
    mysql> show tables;
    Empty set (0.00 sec)
    

I'd very much appreciate any thoughts/advice!


Answer: I think the problem is that the models are not imported. When you do:

    
    
    from app import db
    

you trigger the creation of the SQLAlchemy object, but the models are not
registered. So then `db.create_all()` thinks there are no tables to create.

If you import the models, then they are going to register themselves with the
database object. This may seem odd, because you don't really need to use the
models directly, but it is the only way the database object learns about them.

