Home » Uncategorized » SQLAlchemy FLASK migrate 数据库迁移中的坑!

SQLAlchemy FLASK migrate 数据库迁移中的坑!

  • 如果由多个蓝图下读定义了model模块,在初始化的时候需要加载到上下文中。

当使用flask_Migrate迁移数据库的时候,当执行:

python manage.py db migrate -m '修改说明'

db会默认去上下文中寻找定义的models模型,所以必须在初始化app的时候加载相关models的上下文;因此所有相关的model.py文件都应该在初始化app的时候:

from XXX import model

数据迁移的坑

  1. SQLAlchemy当model发生了修改的时候,其是不能识别字段的的类型和字段大小的。
from extensions import

 db

classUser(db.model)
__tablename__ = 'users
'
    user_id = db.Column(db.String(8), primary_key=True)


 

# 改为
classUser(db.model)
__tablename__ = 'users
'
    user_id = db.Column(db.String(20), primary_key=True)

问题:直接迁移会出现no change,因为不会检测字段的类型。

办法:修改字段的名字迁移后再将字段改回迁移,相当于删除原来的字段重新创建;

  1. 当当前的versions和数据库的版本不一致导致无法迁移时。

办法:

# 删除原来的migrations文件夹;
# 去数据库删除alembic_version表的内容;
# 重新执行数据库迁移操作;

手动初始化SQLAlchemy

在有些时候,我们没有初始化APP,但是又想使用models中定义的模型和数据库的ORM操作,那么就需要手动初始化了。

from sqlalchemy import
 create_engine
from sqlalchemy.orm import
 scoped_session, sessionmaker
from models import

 AdminUser

# 创建一个配置对象

engine = create_engine('mysql+pymysql://username:passwd@ip:port/db?charset=utf8', convert_unicode=True
)
# 创建一个会话

db_session = scoped_session(sessionmaker(autocommit=False
,
                                         autoflush=False

,
                                         bind=engine))
# 初始化查询对象



AdminUser.query = db_session.query_property()

# 下面就跟在框架中一样了


admin = AdminUser()
admin.id = 1




admin.username = username
admin.password = pwd
db_session.add(admin)
db_session.commit()                                         

查询报错:sqlalchemy.exc.InvalidRequestError: Can’t reconnect until invalid transaction is rolled back

  • 原因是:连接断开后,事务没有回滚,残留的锁导致后续的查询报错.sqlalchemy对每一个查询和插入等操作都是一个事务。
  • 解决:在所有的数据库操作的时候捕捉异常进行事务的回滚。
# main.py
from models import
 OrderInfo 
from sqlalchemy.exc import
 InvalidRequestError
try
:
    order = OrderInfo.query.filter_by(task_id=user_dict.get('task_id'
)).first()
    order.status = 'COMPLETE'


    db.session.commit()
except

 InvalidRequestError:
    db.session.rollback()
except Exception as
 e:
    print(e)