14、Flask实战第14天:Flask使用SQLAlchemy
flask-sqlalchemy使用详解
之前我们用到的SQLAchemy是可以单独使用的,不需要用到Flask
如果我们在Flask框架中使用SQLAchemy,可以使用flask_sqlalchemy,这个库能够让我们在flask框架中更加方便的去使用它。
安装flask-sqlalchemy
创建数据库连接,编辑my_flask.py
定义模型,编辑my_flask.py
运行后,查看数据库已经创建了2张表
解决运行时出现的问题
... app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #添加此行配置
添加数据,编辑my_flask.py
... user = User(username='heboan') article = Article(title='title one') article.author = user db.session.add(article) db.session.commit()
查看表已经有数据了
修改数据
... user = db.session.query(User).filter(User.username=='heboan').first() user.username = 'sellsa' db.session.commit()
查询数据
... user = db.session.query(User).filter(User.username=='sellsa').first() print(user)
删除数据
... article = db.session.query(Article).filter(Article.title=='title one').first() db.session.delete(article) db.session.commit()
alembic数据库迁移工具基本使用
之前我们学习的时候,当表模型有变更的时候,是先把改模型先删除再创建。但是在生产环境中这显然是不行的。为了解决这个问题,我们需需要用到alembic工具。
alembic是sqlalchemy的作者开发的。用来做ORM模型与数据库的迁移与映射。alembic使用方式跟git有点类似,表现在两个方面:1‘
1、alembic的所有命令都是以alembic开头
2、alembic的迁移文件也是通过版本进行控制
安装alembic
workon flask-env
pip install alembic
alembic 和sqlalchemy一样,是可以独立于flask单独使用的,这里我们建一个model.py来学习alembic
因此我们就不需要Base.metedata.create_all()了
如何使用alembic
1、初始化alembic仓库,在终端中,cd到你的 项目目录中,然后执行命令alembic init alembic(这个名字可以任意取,但是建议使用alembic,看起来明了),创建一个alembic的仓库
2、定义模型,上面我已经定义好了User模型
3、修改配置文件,alembic.ini
#修改此配置 sqlalchemy.url = mysql+pymysql://root:123456@localhost/heboan?charset=utf8
4、为了使用模型类更新数据库,需要在alembic/env.py文件中设置target_metadata,默认为target_metadata=None。使用sys模块把当前项目的路径导入到path中
... import sys, os sys.path.append(os.path.dirname(os.path.dirname(__file__))) import model ... target_metadata = model.Base.metadata
5、自动生成迁移文件: 使用alembic revision --autogenerate -m "message" 将当前模型的状态生成迁移文件
生成的迁移文件,迁移文件里面有两个函数,一个是upgrade, 一个是downgrade
6、更新数据库:使用alembic upgrade head将刚刚生成的迁移文件,真正映射到数据库中。同理,如果要降级,那么使用alembic downgrade head
查看数据库,可以看到生成了2张表
#######################
我们尝试给user表加个字段age
执行 alembic revision --autogenerate -m " add age column"
打开迁移文件,账面已经记录到我们增加了一个字段age
更新数据库:alembic upgrade head
最后查看数据表结构
命令和参数解释:
init: 创建一个alembic仓库
revision: 创建一个新的版本文件
--autogenerate: 自动将当前模型的修改生成迁移脚本
-m 本次迁移做了哪些修改,用户可以指定这个参数,方便回顾
upgrade: 将指定版本的迁移文件映射到数据库中,会执行版本文件中的upgrade函数。如果有多个迁移脚本没有被映射到数据中,那么会执行多个迁移脚本
head: 代表最新的迁移脚本的版本号,也可以直接指定版本号
downgrade:会执行指定版本的迁移文件中的downgrade函数,指定版本号回退到指定的版本
heads: 展示head指向的脚本文件版本号
histor:列出所有的迁移版本及及其信息
current: 展示出当前数据库中的版本号
经典错误
Flask-SQLAlchemy下alembic的配置
我们前面做的表和版本信息全部删除, model.py也不需要了,直接删除
为了方便管理,我们把之前写在my_flask中的数据库配置放到配置文件config.py里面去
然后我们可以在my_flask.py中定义模型
修改env.py,因此我们定义模型的位置已经变了
... sys.path.append(os.path.dirname(os.path.dirname(__file__))) import my_flask ... target_metadata = my_flask.db.Model.metadata #这里是db.Model而不是Base
现在我们就可以去项目目录执行生成迁移脚本,再更新到数据库中
查看数据库,已经成功创建了表
Flask-Script
Flask-Script的作用是可以通过命令的形式来操作Flask。例如通过命令跑一个开发版本的服务器、设置数据库,定时任务等。要使用Flask-Script,可以通过pip install flask-script安装最新版本。
pip install flask-script
创建一个manage.py来配置flask-script,首先看一个简单的例子,编辑manage.py
也可以传递参数
那么flask-script有一些什么样的实际应用场景呢?
比如我们后台要初始化生成管理员账号(Django就提供了这种功能), 这里我们来简单的演示下, 编辑my_flask.py创建表backend_user
更新到数据库
alembic revision --autogenerate -m "add table backend_user" alembic upgrade head
现在来写manage.py
查看数据库
优化项目结构
目前我们都是把模型表定义的代码全部写在主程序文件my_flask.py, 这显然是不合适的。我们可以单独用一个文件来管理模型表,如果项目较大,还可以用python package分们别类的定义。这里我单独创建一个文件models.py来定义模型。
问题,如果只是使用models.py,会出现循环引用,如下:
因为循环引用报错
为了解决这个问题,我们需要再追加一个文件exts.py
models.py
my_flask.py
Flask-Migrate
在实际开发环境中,经常会发生数据库修改的行为。一般我们修改数据库不会直接手动去修改,而是去修改ORM对应的模型,然后再把模型映射到数据库中。这时候如果有一个工具能专门做这种事情,就显得非常有用了,而flask-migrate就是做这个事情的。flask-migrate是基于Alembic进行的一个封装,并集成到Flask中,而所有的迁移操作其实都是Alembic做的,它能跟踪模型的变化,并将变化映射到数据库中。
flask-migrate需要安装,命令如下:
pip install flask-migrate
flask-migrate需要结合flask-script
创建manage.py,代码如下
运行命令初始化迁移文件
python manage.py db init
运行命令将模型的映射添加到文件中, 以后有更新只需要执行 一下两条命令就可以了
python manage.py db migrate
最后将映射文件真正映射到数据库
python manage.py db upgrade
flask-sqlalchemy总结
通过以上的学习,我们在开发flask项目用sqlalchemy的时候,只需要做如下操作:
安装如下库
pip install pymysql pip install flask-sqlalchemy pip install flask-script pip install flask-migrate
配置文件config.py配置数据库连接信息
... # Database HOST = '127.0.0.1' PORT = '3306' USERNAME = 'root' PASSWORD = '123456' DATABASE = 'heboan' DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset-utf8'.format(username=USERNAME, password=PASSWORD, host=HOST, port=PORT, db=DATABASE) SQLALCHEMY_DATABASE_URI = DB_URI SQLALCHEMY_TRACK_MODIFICATIONS = False
定义一个exts.py文件用来初始化SQLAlchemy
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
定义一个models.py文件专门用来管理模型类
from exts import db class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(30), nullable=False) ...
在主程序my_flask.py中引入配置文件,并且给初始化的db传入app
from flask import Flask import config from exts import db app = Flask(__name__) app.config.from_object(config) db.init_app(app) ...
定义一个manage.py通过flask-script和flask-migrate来完成数据库修改的功能
from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from my_flask import app from exts import db from models import User #这里要把需要更新的表类导入,否则不会发生变更 migrate = Migrate(app, db) manager = Manager(app) manager.add_command('db', MigrateCommand) if __name__ == '__main__': manager.run()
初始化迁移脚本
>workon flask-env(项目虚拟环境)
>python manage.py db init
执行后,会在项目目录下生成migrations 包
当我们在models.py对模型类进行增删修改操作后,就可以执行一下命令生成迁移脚本
>python manage.py db migrate
执行完成后,可以在migrations/versions下看到对应版本的迁移脚本,里面记录了发生的变更操作
最后,我们需要把这些变更操作映射到数据库
python manage.py db upgrade
数据库中就会对我们的变更进行修改操作,并且有一个表alembic_version记录了当前的版本
python manage.py db xxxx 还支持很多其他命令,我们可以通过python manage.py db --help查看命令帮助
(flask-env) D:\my_flask>python manage.py db --help usage: Perform database migrations Perform database migrations positional arguments: {init,revision,migrate,edit,merge,upgrade,downgrade,show,history,heads,branches,current,stamp} init Creates a new migration repository revision Create a new revision file. migrate Alias for 'revision --autogenerate' edit Edit current revision. merge Merge two revisions together. Creates a new migration file upgrade Upgrade to a later version downgrade Revert to a previous version show Show the revision denoted by the given symbol. history List changeset scripts in chronological order. heads Show current available heads in the script directory branches Show current branch points current Display the current revision for each database. stamp 'stamp' the revision table with the given revision; don't run any migrations optional arguments: -?, --help show this help message and exit