Hi @miguelgrinberg.
I'm trying to add flask-migrate to an existing model with data. My first migration is adding a boolean column called enabled with default True.
class Prediction(db.Model):
id = db.Column(db.String(32), primary_key=True)
...
enabled = db.Column(db.Boolean, default=True)
...
The upgrade method of the migration is generated as following:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('prediction', sa.Column('enabled', sa.Boolean(), nullable=False))
# ### end Alembic commands ###
Applying this migration makes enabled with default as False.
Changing the migration to:
op.add_column('prediction', sa.Column('enabled', sa.Boolean(), nullable=False, default=True))
also makes enabled False by default.
Using server_default makes this error appear on flask db init:
sqlalchemy.exc.ArgumentError: Argument 'arg' is expected to be one of type '<class 'str'>' or '<class 'sqlalchemy.sql.elements.ClauseElement'>' or '<class 'sqlalchemy.sql.elements.TextClause'>', got '<class 'bool'>'
Am i doing something wrong? Thanks
Can you share the code that you used with server_default and the complete error message including the stack trace?
The default argument is not going to work in a migration, because that is a SQLAlchemy level default, not a database default.
Hi @miguelgrinberg, thanks for replying.
I tried server_default just with the value True passed to the column, .
enabled = db.Column(db.Boolean, nullable=False, server_default=True)
Here's the stack trace:
Traceback (most recent call last):
File "x/env/lib/python3.6/site-packages/flask/cli.py", line 529, in list_commands
rv.update(info.load_app().cli.list_commands(ctx))
File "x/env/lib/python3.6/site-packages/flask/cli.py", line 377, in load_app
raise_if_not_found=False)
File "x/env/lib/python3.6/site-packages/flask/cli.py", line 235, in locate_app
__import__(module_name)
File "x/app/__init__.py", line 4, in <module>
from app.blueprints import ACTIVE
File "x/app/blueprints/__init__.py", line 4, in <module>
from app.blueprints.predictor import feed, syi, ensemble # noqa
File "x/app/blueprints/predictor/feed.py", line 5, in <module>
from app.blueprints.predictor.utils import (
File "/Users/cogarcia/dev/pyme-primeraventa-nomaquinable/app/blueprints/predictor/utils.py", line 7, in <module>
from app.bin.unsubscribe_item import CONTROL_GROUP_PROBABILITY
File "x/app/bin/unsubscribe_item.py", line 16, in <module>
from app.models.models import Prediction
File "x/app/models/models.py", line 5, in <module>
class Prediction(db.Model):
File "x/app/models/models.py", line 13, in Prediction
enabled = db.Column(db.Boolean, nullable=False, server_default=True)
File "x/env/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 1266, in __init__
args.append(DefaultClause(self.server_default))
File "x/env/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 2456, in __init__
TextClause), 'arg')
File "x/env/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 1104, in assert_arg_type
(name, ' or '.join("'%s'" % a for a in argtype), type(arg)))
sqlalchemy.exc.ArgumentError: Argument 'arg' is expected to be one of type '<class 'str'>' or '<class 'sqlalchemy.sql.elements.ClauseElement'>' or '<class 'sqlalchemy.sql.elements.TextClause'>', got '<class 'bool'>'
The server_default should be given as text in the native format of the database, not as a Python type. See https://docs.sqlalchemy.org/en/13/core/metadata.html#sqlalchemy.schema.Column.params.server_default.
Should i be using server_default though? I just want every row to have the value of the new column set to True.
you have two options, either set the server default, or else create the column as nullable, then set it to your default using an UPDATE statement, and finally switch it to non-nullable.
I have close to a hundred millions rows, i guess server_default will do.
Thanks so much for the help and your Flask contributions. Your blog got me into Flask.
If it's not too much to ask, how would you describe the server_default as True?
Thanks again
Depends on the database that you are using. server_default='true' or server_default='1' are likely choices.
Thanks, i'll try that. Im closing this issue.
thanks, that鈥檚 help me a lot
thank you
Most helpful comment
Depends on the database that you are using.
server_default='true'orserver_default='1'are likely choices.