flask-sqlalchemy使用及数据迁移
flask-sqlalchemy是flask框架在sqlalchemy基础上改造的一个orm框架
现在有两个实体Article文章和Category分类
一个分类下可能有多篇文章
相关示例:
项目相关结构截图
定义基类BaseModel
from sqlalchemy import Column,String,Integer,Text,DateTime,ForeignKey from flask_sqlalchemy import SQLAlchemy from datetime import datetime db=SQLAlchemy() class BaseModel(db.Model): __abstract__=True ##加了该属性后生成表的时候不会生成该表 id=Column(Integer,primary_key=True,autoincrement=True) addtime=Column(DateTime) status=Column(Integer,default=1) ##初始化构造函数 def __init__(self): self.addtime=datetime.now()
子类Article继承BaseModel
from app.models.base import BaseModel,db from datetime import datetime from sqlalchemy import Column,String,Integer,Text,DateTime,ForeignKey from sqlalchemy.orm import relationship ##文章类 class Article(BaseModel): __tablename__ ='article' ##数据库对应的表名 desction=Column(String(256)) title=Column(String(64),nullable=True) author=Column(String(64),default='未知作者') cover_img=Column(String(128)) source_link_url=Column(String(128)) content=Column(Text) view_count=Column(Integer,default=0) ##relationship用户指定实体模型对应关系,这里的Category指的是实体里编写的类名,区分大小写 category1=relationship('Category') ##category.id里的category指的是上句category接收的变量名,id列名 ##ForeignKey表示外键 categroy_id=Column(Integer,ForeignKey('category1.id')) def __init__(self): self.addtime=datetime.now() ##添加数据 def add(self,article): try: db.session.add(article) db.session.commit() except Exception as e: db.session.rollback() print(e) raise e pass
子类category继承BaseModel
from app.models.base import BaseModel,db from datetime import datetime from sqlalchemy import Column,String,Integer,Text,DateTime,ForeignKey ##分类 class Category(BaseModel): __tablename__ ='category' ##指定生成时数据库里的表名 name=Column(String(64),unique=True,nullable=False) def __init__(self): super(Category,self).__init__()
初始化调用生成表结构
from flask import Flask from app.models.base import db # from app.spider import cn_blogs ##实例化全局app对象 def create_app(): app = Flask(__name__) ##核心代码 app.config.from_object('app.config.setting') db.init_app(app) ##入站操作 with app.app_context(): # pass ##创建表结构 db.create_all() # cn_blogs.get_article_list('https://news.cnblogs.com/') return app
数据迁移
,因为采用'db.create_all'在后期修改数据库表字段的时候,不会自动的映射到数据库中,必须删除表,
然后重新运行'db.create_all' 才会重新映射。这样不符合我们的要求,因此flask-migrate就是为了解决
这个问题。它可以在每次修改模型(class)后,可以将修改的字段映射到数据库中
flask数据迁移主要依赖两个模块lask-migrate和flask-script
flask-migrate用到的常用命令:
init: 初始化
migrate:生成迁移文件
upgrade:提交数据库更改操作
downgrade :回滚到上一步操作
在pipenv中自行安装f lask-migrate和flask-script
现数据库中article表相关信息
在上表article中,如果想添加一个排序字段sort_id
sort_id=Column(Integer,default=99)
在根目录run.py如下代码
from flask_migrate import Migrate,MigrateCommand from flask_script import Manager,Shell from app import create_app,db from app.models.messaage import Message app=create_app() ##数据迁移关键代码 manage = Manager(app) # 第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例 migrate = Migrate(app, db) # manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令 manage.add_command('db', MigrateCommand) if __name__ == '__main__': ##调用迁移的入口方法 manage.run() #app.run(port=3000, debug=True,threaded=True)
右键run.py文件运行
点击底部terminal执行命令行 :python run.py db init
run.py为Manage所在的文件名
执行命令后会在项目根目录下生成一个名为migrations的文件目录,如果该目录存在的话则不会再次生成
运行
执行python run.py db migrate
这里会自动生成模型修改的字段信息,并记录在migrations文件夹里
执行 python run.py db upgrade
将会将执行 里面的upgrade函数,更新到数据库里,这里执行命令的时候建议先去检查下更新的字段是否无误后再执行操作
这时候再来看数据库
sort_id字段已经成功更新到数据库article表里了
同理,如果更新错了,想回到上一步没更新之前的状态,执行downgrade命令,实现回滚操作
downgrade执行的是migrations文件夹里downgrade函数,具体可以查看该函数内部实现
执行 python run.py db downgrade 命令
这时候再来看数据库article表结构
这里还有个小问题:发现如果是创建新表的时候只能调用db.create_all()来创建,flask-migrate目前好像不支持