title: Flask-migrate: change model attributes and rename corresponding database columns
body: <p>I have a bit of experience with Flask but not very much with databases (Flask-migrate / alembic / SqlAlchemy). </p>
  
  <p>I'm following <a href="https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database" rel="nofollow noreferrer">this</a> tutorial and things are working quite alright.</p>
  
  <p>I have a User model like this:</p>
  
  <pre><code># user_model.py
  
  from app import DB
  ... other imports
  
  class User(UserMixin, DB.Model):
  
      __tablename__ = 'users'
      id = DB.Column(DB.Integer, primary_key=True)
      username = DB.Column(DB.String(64), index=True, unique=True)
      email = DB.Column(DB.String(120), index=True, unique=True)
      password_hash = DB.Column(DB.String(128))
  </code></pre>
  
  <p>I can then initialize the db, do migrations, upgrades etc.</p>
  
  <p>The problem started when I wanted to change that <em>id</em> attribute, which in Python is not a great variable name choice. Let's say I want to rename that to <em>user_id</em> instead.</p>
  
  <p>Now obviously the db already exists and there is some data inside. I thought maybe by some kind of magic from Flask-Migrate/Alembic just modifying the User class would work. That is just change the id line above to:</p>
  
  <pre><code>user_id = DB.Column(DB.Integer, primary_key=True)
  </code></pre>
  
  <p>If I do this and run <code>flask db migrate</code> I get:</p>
  
  <pre><code>INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
  INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
  INFO  [alembic.autogenerate.compare] Detected added column 'users.user_id'
  INFO  [alembic.autogenerate.compare] Detected removed column 'users.id'
  </code></pre>
  
  <p>So actually Alembic detects this as a column being removed and a new one added, which I suppose makes sense.</p>
  
  <p>But this in fact doesn't work if I run <code>flask db upgrade</code>. I get the following error:</p>
  
  <blockquote>
    <p>ERROR [alembic.env] (sqlite3.OperationalError)  Cannot add a NOT NULL
    column with default value NULL [SQL: 'ALTER TABLE users ADD COLUMN
    user_id INTEGER NOT NULL']</p>
  </blockquote>
  
  <p>The error is quite clear. The point is that I don't want to add a new column, I just want to rename an existing one.</p>
  
  <p>Looking around I also tried to modify the <code>script.py</code> handling the upgrade to use the alter_column method:</p>
  
  <pre><code>def upgrade():
      ${upgrades if upgrades else "pass"}
      # just added this line below
      op.alter_column('users', 'id', nullable=False, new_column_name='user_id')
  </code></pre>
  
  <p>However this also doesn't seem to work (I get the same error as above).</p>
  
  <p>So the question boils down to a very simple one: how do I rename a database columns in a Flask app using Flask-Migrate? Or in other words, if I wish to modify the attributes of a given model, what do I have to do so that the corresponding column names in the database are correctly renamed?</p>