GVKun编程网logo

配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库

11

在本文中,我们将带你了解配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的23.Flask操作Mysql数据

在本文中,我们将带你了解配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的23. Flask 操作Mysql数据库 - flask-sqlalchemy扩展、5.5 使用Flask-SQLAlchemy管理数据库、6、使用Flask-SQLAlchemy管理数据库和数据库的迁移、Flask 中使用 Flask-SQLAlchemy 查询数据库在数据库内容更新时无法实时返回

本文目录一览:

配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库

配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库

我有一个使用Flask-SQLAlchemy的Flask应用,并且正在尝试将其配置为使用Flask-Restless软件包使用多个数据库。

根据文档,配置模型以使用多个数据库__bind_key__似乎非常简单。

但是,它似乎不适用于我。

我创建我的应用程序并初始化数据库,如下所示:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

SQLALCHEMY_DATABASE_URI = 'postgres://db_user:db_pw@localhost:5432/db_name'
SQLALCHEMY_BINDS = {
    'db1': SQLALCHEMY_DATABASE_URI,'db2': 'mysql://db_user:db_pw@localhost:3306/db_name'
}

app = Flask(__name__)
db = SQLALchemy(app)

然后定义包括在内的模型__bind_key__,这些模型应该告诉SQLAlchemy它需要使用哪个数据库:

class PostgresModel(db.Model):

    __tablename__ = 'postgres_model_table'
    __bind_key__ = 'db1'

    id = db.Column(db.Integer,primary_key=True)
    ...


class MySQLModel(db.Model):

    __tablename__ = 'mysql_model_table'
    __bind_key__ = 'db2'

    id = db.Column(db.Integer,primary_key=True)
    ...

然后我像这样启动Flask-Restless:

manager = restless.APIManager(app,flask_sqlalchemy_db=db)
manager.init_app(app,db)

auth_func = lambda: is_authenticated(app)

manager.create_api(PostgresModel,methods=['GET'],collection_name='postgres_model',authentication_required_for=['GET'],authentication_function=auth_func)

manager.create_api(MySQLModel,collection_name='mysql_model',authentication_function=auth_func)

该应用程序运行良好,当我点击时,我http://localhost:5000/api/postgres_model/[id]从Postgres
DB中获得了对象的预期JSON响应(我猜这是因为我在SQLALCHEMY_DATABASE_URI中拥有凭据)。

尽管当我点击时http://localhost:5000/api/mysql_model/[id],我得到一个mysql_model_table不存在的错误,表明它在Postgres
DB中查找,而不是MySQL中。

我在这里做错了什么?

23. Flask 操作Mysql数据库 - flask-sqlalchemy扩展

23. Flask 操作Mysql数据库 - flask-sqlalchemy扩展

官网文档

https://flask-sqlalchemy.palletsprojects.com/en/master/quickstart/

数据库的设置

Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表中表示的实体的数据属性。比如:商品表里有name、price、number等。 Flask本身不限定数据库的选择,你可以选择sql或NOsql的任何一种。也可以选择更方便的sqlALchemy,类似于Django的ORM。sqlALchemy实际上是对数据库的抽象,让开发者不用直接和sql语句打交道,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。

sqlAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了sqlAlchemy操作的flask扩展。

下面使用MysqL作为示例进行说明。

创建MysqL数据库

1.登录数据库

MysqL -u root -p password

2.创建数据库,并设定编码

create database <数据库名> charset=utf8;

3.显示所有数据库

show databases;

4.执行如下

MysqL> create database flask_ex charset=utf8;
Query OK, 1 row affected (0.06 sec)

安装flask-sqlalchemy的扩展

pip install -U Flask-sqlAlchemy

python2:要连接MysqL数据库,仍需要安装flask-MysqLdb

pip install flask-MysqLdb

python3:要连接MysqL数据库,仍需要安装pyMysqL

pip install pyMysqL

本篇章内容以python3作为开讲。

使用Flask-sqlAlchemy连接MysqL数据库

使用Flask-sqlAlchemy扩展操作数据库,首先需要建立数据库连接。数据库连接通过URL指定,而且程序使用的数据库必须保存到Flask配置对象的sqlALCHEMY_DATABASE_URI键中。

对比下Django和Flask中的数据库设置:

Django的数据库设置:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.MysqL', # 修改后端数据库使用MysqL
'NAME': 'mydb', # 设置访问数据库名称
'USER': 'root', # 访问访问MysqL用户名
'PASSWORD': 'password', # 设置访问密码
'HOST': 'localhost', # 设置访问ip地址
'PORT': 3306, # 设置访问端口号
}
}

Flask的数据库设置:

app.config['sqlALCHEMY_DATABASE_URI'] = 'MysqL://root:MysqL@127.0.0.1:3306/flask_ex'

常用的sqlAlchemy字段类型

上面看完了如何设置连接数据库,那么来看看,使用sqlAlchemy创建数据模型的时候,基本的字段类型如下:

类型名 python中类型 说明
Integer int 普通整数,一般是32位
SmallInteger int 取值范围小的整数,一般是16位
BigInteger int或long 不限制精度的整数
Float float 浮点数
Numeric decimal.Decimal 普通整数,一般是32位
String str 变长字符串
Text str 变长字符串,对较长或不限长度的字符串做了优化
Unicode unicode 变长Unicode字符串
UnicodeText unicode 变长Unicode字符串,对较长或不限长度的字符串做了优化
Boolean bool 布尔值
Date datetime.date 时间
Time datetime.datetime 日期和时间
LargeBinary str 二进制文件

常用的sqlAlchemy列选项

选项名 说明
primary_key 如果为True,代表表的主键
unique 如果为True,代表这列不允许出现重复的值
index 如果为True,为这列创建索引,提高查询效率
nullable 如果为True,允许有空值,如果为False,不允许有空值
default 为这列定义默认值

常用的sqlAlchemy关系选项

选项名 说明
backref 在关系的另一模型中添加反向引用
primary join 明确指定两个模型之间使用的联结条件
uselist 如果为False,不使用列表,而使用标量值
order_by 指定关系中记录的排序方式
secondary 指定多对多中记录的排序方式
secondary join 在sqlAlchemy中无法自行决定时,指定多对多关系中的二级联结条件

上面这些有很多基本选项的说明,下面来进行数据库的基本增删改等操作来加强理解。

数据库基本操作

在Flask-sqlAlchemy中,插入、修改、删除操作,均由数据库会话管理。会话用db.session表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用commit()方法提交会话。

数据库会话是为了保证数据的一致性,避免因部分更新导致数据不一致。提交操作把会话对象全部写入数据库,如果写入过程发生错误,整个会话都会失效。

数据库会话也可以回滚,通过db.session.rollback()方法,实现会话提交数据前的状态。

在Flask-sqlAlchemy中,查询操作是通过query对象操作数据。最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。

下面先来创建两个表的数据模型:用户表和角色表。

在视图函数中定义模型类

看完了上面那么多的概念说明,下面来看看如何创建数据模型以及创建数据表,如下:

1.在脚本15_sqlAlchemy.py编写创建User和Role数据模型

from flask import Flask
from flask_sqlalchemy import sqlAlchemy
import pyMysqL
pyMysqL.install_as_MysqLdb()

app = Flask(__name__)

class Config(object):
"""配置参数"""
# 设置连接数据库的URL
user = 'root'
password = '********'
database = 'flask_ex'
app.config['sqlALCHEMY_DATABASE_URI'] = 'MysqL://%s:%s@127.0.0.1:3306/%s' % (user,password,database)

# 设置sqlalchemy自动更跟踪数据库
sqlALCHEMY_TRACK_MODIFICATIONS = True

# 查询时会显示原始sql语句
app.config['sqlALCHEMY_ECHO'] = True

# 禁止自动提交数据处理
app.config['sqlALCHEMY_COMMIT_ON_TEARDOWN'] = False

# 读取配置
app.config.from_object(Config)

# 创建数据库sqlalchemy工具对象
db = sqlAlchemy(app)

class Role(db.Model):
# 定义表名
__tablename__ = 'roles'
# 定义字段
id = db.Column(db.Integer, primary_key=True,autoincrement=True)
name = db.Column(db.String(64), unique=True)
users = db.relationship('User',backref='role') # 反推与role关联的多个User模型对象

class User(db.Model):
# 定义表名
__tablename__ = 'users'
# 定义字段
id = db.Column(db.Integer, primary_key=True,autoincrement=True)
name = db.Column(db.String(64), unique=True, index=True)
email = db.Column(db.String(64),unique=True)
pswd = db.Column(db.String(64))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # 设置外键

if __name__ == '__main__':

# 删除所有表
db.drop_all()

# 创建所有表
db.create_all()
  1. 执行脚本,创建数据库
python3 15_sqlAlchemy.py

3.在MysqL查看已经创建的表结构

MysqL> show tables;
+--------------------+
| Tables_in_flask_ex |
+--------------------+
| roles |
| users |
+--------------------+
2 rows in set (0.00 sec)

MysqL>
MysqL> desc users;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | YES | UNI | NULL | |
| email | varchar(64) | YES | UNI | NULL | |
| pswd | varchar(64) | YES | | NULL | |
| role_id | int(11) | YES | MUL | NULL | |
+---------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

MysqL>
MysqL> desc roles;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

MysqL>

创建好了数据表之后,下面来看看如何执行数据的增删查改的。

常用的sqlAlchemy查询过滤器

过滤器 说明
filter() 把过滤器添加到原查询上,返回一个新查询
filter_by() 把等值过滤器添加到原查询上,返回一个新查询
limit 使用指定的值限定原查询返回的结果
offset() 偏移原查询返回的结果,返回一个新查询
order_by() 根据指定条件对原查询结果进行排序,返回一个新查询
group_by() 根据指定条件对原查询结果进行分组,返回一个新查询

常用的sqlAlchemy查询执行器

方法 说明
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果,如果未查到,返回None
first_or_404() 返回查询的第一个结果,如果未查到,返回404
get() 返回指定主键对应的行,如不存在,返回None
get_or_404() 返回指定主键对应的行,如不存在,返回404
count() 返回查询结果的数量
paginate() 返回一个Paginate对象,它包含指定范围内的结果

创建表:

db.create_all()

删除表

db.drop_all()

每次插入单条数据


if __name__ == '__main__':

# 插入一条角色数据
role1 = Role(name='admin')
db.session.add(role1)
db.session.commit()

# 再次插入一条数据
role2 = Role(name='user')
db.session.add(role2)
db.session.commit()

执行脚本:

python3 15_sqlAlchemy.py

在MysqL中查看插入的数据,如下:

MysqL> select * from roles \G
*************************** 1. row ***************************
id: 1
name: admin
*************************** 2. row ***************************
id: 2
name: user
2 rows in set (0.00 sec)

一次插入多条数据

    # 一次性插入多条数据
user1 = User(name='wang',email='wang@163.com',pswd='123456',role_id=role1.id)
user2 = User(name='zhang',email='zhang@189.com',pswd='201512',role_id=role2.id)
user3 = User(name='chen',email='chen@126.com',pswd='987654',role_id=role2.id)
user4 = User(name='zhou',email='zhou@163.com',pswd='456789',role_id=role1.id)
db.session.add_all([user1,user2,user3,user4])
db.session.commit()

执行插入数据,如下:

python3 15_sqlAlchemy.py

在MysqL中查询插入的数据如下:

MysqL> select * from users \G
*************************** 1. row ***************************
id: 1
name: wang
email: wang@163.com
pswd: 123456
role_id: 1
*************************** 2. row ***************************
id: 2
name: zhang
email: zhang@189.com
pswd: 201512
role_id: 2
*************************** 3. row ***************************
id: 3
name: chen
email: chen@126.com
pswd: 987654
role_id: 2
*************************** 4. row ***************************
id: 4
name: zhou
email: zhou@163.com
pswd: 456789
role_id: 1
4 rows in set (0.00 sec)

MysqL>

虽然这里在python中看上去是一次性插入多条数据,其实在MysqL也是执行多行插入的语句,通过MysqL的日志可以看到如下:

2019-11-23T16:48:56.984459Z	 9061 Query	INSERT INTO users (name, email, pswd, role_id) VALUES ('wang', 'wang@163.com', '123456', 1)
2019-11-23T16:48:56.997132Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhang', 'zhang@189.com', '201512', 2)
2019-11-23T16:48:57.010175Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('chen', 'chen@126.com', '987654', 2)
2019-11-23T16:48:57.024134Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhou', 'zhou@163.com', '456789', 1)

实际上并没有将多个values合并到一个insert语句,依然是多个insert语句逐个插入的。

查询:filter_by精确查询

返回名字等于wang的所有user

User.query.filter_by(name='wang').all()

在交互模型执行如下:

>python3 db_demo.py shell
In [1]: from db_demo import User

In [2]: User.query.filter_by(name='wang').all()
Out[2]: [<User 1>]

In [3]:

first()返回查询到的第一个对象

User.query.first()

执行如下:

In [3]: User.query.first()
Out[3]: <User 1>

all()返回查询到的所有对象

User.query.all()

执行如下:

In [4]: User.query.all()
Out[4]: [<User 1>, <User 2>, <User 3>, <User 4>]

In [5]:

filter模糊查询,返回名字结尾字符为g的所有数据。

User.query.filter(User.name.endswith('g')).all()

执行如下:

In [5]: User.query.filter(User.name.endswith('g')).all()
Out[5]: [<User 1>, <User 2>]

get(),参数为主键,如果主键不存在没有返回内容

User.query.get()

执行如下:

In [6]: User.query.get(2)
Out[6]: <User 2>

In [7]: user2 = User.query.get(2)

In [8]: user2.name
Out[8]: 'zhang'

逻辑非,返回名字不等于wang的所有数据。

User.query.filter(User.name!='wang').all()

执行如下:

In [9]: User.query.filter(User.name!='wang').all()
Out[9]: [<User 2>, <User 3>, <User 4>]

逻辑与,需要导入and*,返回and*()条件满足的所有数据。

from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()

执行如下:

In [10]: from sqlalchemy import and_

In [15]: users = User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()

In [16]: for user in users:
...: print(user.email)
...:
zhou@163.com

逻辑或,需要导入or_

from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()

执行如下:

In [17]: from sqlalchemy import or_

In [18]: users = User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()

In [19]: for user in users:
...: print(user.name, user.email)
...:
wang wang@163.com
zhang zhang@189.com
chen chen@126.com
zhou zhou@163.com

In [20]:

not_ 相当于取反

from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()

执行如下:

In [22]: from sqlalchemy import not_

In [25]: users = User.query.filter(not_(User.name=='chen')).all()

In [26]: for user in users:
...: print(user.name, user.email)
...:
wang wang@163.com
zhang zhang@189.com
zhou zhou@163.com

查询数据后删除

user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()

执行如下:

(venv) $ >python3 db_demo.py shell

In [1]: from db_demo import User

In [3]: user = User.query.first()

In [5]: from db_demo import db

In [6]: db.session.delete(user)

In [7]: db.session.commit()

In [8]: User.query.all()
Out[8]: [<User 2>, <User 3>, <User 4>]

更新数据

user = User.query.first()
user.name = 'dong'
db.session.commit()
User.query.first()

执行如下:

In [1]: from db_demo import User

In [5]: from db_demo import db

In [9]: user = User.query.first()

In [10]: user
Out[10]: <User 2>

In [11]: user.name
Out[11]: 'zhang'

In [12]: user.name = 'dong'

In [13]: db.session.commit()

In [14]: user = User.query.first()

In [15]: user.name
Out[15]: 'dong'

使用update

User.query.filter_by(name='zhang').update({'name':'li'})

执行如下:

In [21]: User.query.filter_by(name='dong').update({'name':'li'})
Out[21]: 0

In [22]: User.query.get(2)
Out[22]: <User 2>

In [23]: user = User.query.get(2)

In [24]: user.name
Out[24]: 'li'

关联查询示例:角色和用户的关系是一对多的关系,一个角色可以有多个用户,一个用户只能属于一个角色。

关联查询角色的所有用户:

#查询roles表id为1的角色
role1 = Role.query.get(1)
#查询该角色的所有用户
role1.users

执行如下:

In [25]: from db_demo import Role

In [26]: role1 = Role.query.get(1)

In [27]: role1.users
Out[27]: [<User 4>]

In [28]: role2 = Role.query.get(2)

In [29]: role2.users
Out[29]: [<User 2>, <User 3>]

关联查询用户所属角色:

#查询users表id为3的用户
user1 = User.query.get(3)
#查询用户属于什么角色
user1.role

执行如下:

In [30]: user1 = User.query.get(3)

In [31]: user1.role
Out[31]: <Role 2>

 

5.5 使用Flask-SQLAlchemy管理数据库

5.5 使用Flask-SQLAlchemy管理数据库

Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 应用中使用 SQLAlchemy 的操作。 SQLAlchemy 是一个强大的关系型数据库框架,支持多种数据库后台。SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能。

与其他多数扩展一样,Flask-SQLAlchemy 也使用 pip 安装:

pip3 install flask-sqlalchemy

在 Flask-SQLAlchemy 中,数据库使用 URL 指定。几种最流行的数据库引擎使用的URL格式如表 5-1 所示。

表5-1:FLask-SQLAlchemy数据库URL

数据库引擎 URL
MySQL mysql://username:password@hostname/database
Postgres postgresql://username:password@hostname/database
SQLite(Linux,macOS) sqlite:////absolute/path/to/database
SQLite(Windows) sqlite:///c:/absolute/path/to/database

在这些 URL 中,hostname 表示数据库服务所在的主机,可以是本地主机(localhost),也可以是远程服务器。数据库服务器上可以托管多个数据库,因此 database 表示要使用的数据库名。如果数据库需要验证身份,使用 username 和 password 提供数据库用户的凭据。

  • SQLite 数据库没有服务器,因此不用指定 hostname、username 和 password。URL 中的 database 是磁盘中的文件名。

应用使用的数据库 URL 必须保存到 Flask 配置对象的 SQLALCHEMY_DATABASE_URI 键中。

Flask-SQLAlchemy 文档还建议把 SQLALCHEMY_TRACK_MODIFICATIONS 键设为 False,以便在不需要跟踪对象变化时降低内存消耗。其他配置选项的作用参阅 Flask-SQLAlchemy 的文档。

示例 5-1 展示如何初始化及配置一个简单的 SQLite 数据库。

示例 5-1 hello.py:配置数据库

import os
from flask_sqlalchemy import SQLAlchemy

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__) 
app.config[''SQLALCHEMY_DATABASE_URI''] =\
    ''sqlite:///'' + os.path.join(basedir, ''data.sqlite'') app.config[''SQLALCHEMY_TRACK_MODIFICATIONS''] = False

db = SQLAlchemy(app)

db 对象是 SQLAlchemy 类的实例,表示应用使用的数据库,通过它可获得 Flask-SQLAlchemy提供的所有功能。

《基于Python的Web应用开发实战(第二版)》

6、使用Flask-SQLAlchemy管理数据库和数据库的迁移

6、使用Flask-SQLAlchemy管理数据库和数据库的迁移

 

使用Flask-SQLAlchemy管理数据库

在视图函数中操作数据库

使用Flask-Migrate实现数据库的迁移


1、安装Flask-SQLAlchemy

 

 

 

2、hello.py配置数据库

from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
manager = Manager(app)
app.config[''SQLALCHEMY_DATABASE_URI''] = ''sqlite:///data.sqlite''
app.config[''SQLALCHEMY_TRACK_MODIFICATIONS''] = True
db = SQLAlchemy(app)

 

3、hello.py 定义Role和User模型

类变量__tablename__定义在数据库中使用的表名。如果没有定义,Flask-SQLAlchemy会使用一个默认的名字,但默认的表名没有遵守使用复数形式进行命名的约定,最好由我们自己指定表名。其余变量都是该模型的属性,被定义为db.Cloumn类的实例

#定义数据库模型
class Role(db.Model):
    __tablename__ = ''roles''
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)

    def __repr__(self):
        return ''<Role %r>'' %self.name

class User(db.Model):
    __tablename__ = ''users''
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)

    def __repr__(self):
        return ''User %r'' %self.username

 

4、关系
users = db.relation(''User'', backref=''role'')

添加到Role模型中的users属性代表这个关系的面向对象视角。对于一个Role类的实例,其users属性将返回与角色相关联的用户组成的列表。
db.relationship()第一个参数表明这个关系的另一端是哪个模型(类)。如果模型类尚未定义,可使用字符串形式指定。
db.relationship()第二个参数backref,将向User类中添加一个role属性,从而定义反向关系。这一属性可替代role_id访问Role模型,此时获取的是模型对象,而不是外键的值。

 

role_id = db.Column(db.Integer, db.ForeignKey(''roles.id''))

这句话是说,User类中添加了一个role_id变量,数据类型db.Integer,第二个参数指定外键是哪个表中哪个id

 

当表之间的关系是一对一的关系时,可添加userlist参数

db.Relationship(''User'',backref=''role'',uselist=False)

 

 

5、在shell中创建数据库

在shell中激活虚拟环境,运行python hello.py shell


我们要让 Flask-SQLAlchemy 根据模型类创建数据库。方法是使用 db.create_all()函数,执行完后,目录下会多一个data.sqlite的文件

6、生成data.sqlite文件后,在pycharm中需下载相应包进行支持,否则数据库不能用

 

 


如果没有下载相应文件,红框处会有下载提示,点击下载即可

 

 

6、插入行
创建一些角色和用户

from hello import Role, User
admin_role = Role(name=''Admin'')
mod_role = Role(name=''Moderator'')
user_role = Role(name=''User'')
user_john = User(username=''john'', role=admin_role)
user_susan = User(username=''susan'', role=user_role)
user_david = User(username=''david'', role=user_role)

 


此时新建对象的id属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的,现在这些对象只存在于python中,还未写入数据库,因此id未赋值

在 Flask-SQLAlchemy 中,会话由 db.session表示。准备把对象写入数据库之前,先要将其添加到会话中

db.session.add(admin_role)
db.session.add(mod_role)
db.session.add(user_role)
db.session.add(user_john)
db.session.add(user_susan)
db.session.add(user_david)

 


也可简写为:

db.session.add_all([admin_role, mod_role, user_role,... user_john, user_susan, user_david])


提交到会话

db.session.commit()

 roles表                                                                         users表

SELECT * FROM roles                         SELECT * FROM users

                

说明:

users表中的用户拥有唯一的角色,在users表中定义role_id并设置属性为外键,在roles表中给users表添加role属性,该属性可以替代users表中的role_id访问roles模型

 user_john = User(username=''john'', role=admin_role)  可以看到可以通过role属性,访问了roles表中的id,并通过设置的关系,自动关联users表中role_id 和roles表中的id列

 

 

7、修改行

admin_role.name = ''Administrator''
db.session.add(admin_role)
db.session.commit()

roles表状态

 

 

8、删除行

db.session.delete(mod_role)
db.session.commit()

roles表状态

 

9、查询行

Flask-SQLAlchemy为每个模型类都提供了query对象,最基本的模型查询对象是取回对应表中的所有记录:

 

 使用过滤器可以配置query对象进行更精确的数据库查询,下面是查找角色为“User”的所有用户

 

 若要查看SQLAlchemy为查询生成的原生SQL查询语句,只需把query对象转换成字符串:

 

 退出shell后,重新打开一个shell会话,就要从数据库中读取行,再重新创建python对象,下面是发起一个查询,加载名为“User”的用户角色

 

 filter_by()等过滤器在query对象上调用,返回一个更精确的query对象。多个过滤器可以一起调用,知道获取结果

 

在视图函数中操作数据库

1、修改hello.py中的index方法

@app.route(''/'', methods=[''GET'', ''POST''])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username = form.name.data)
            db.session.add(user)
            session[''known''] = False
        else:
            session[''known''] = True
        session[''name''] = form.name.data
        form.name.data = ''''
        return redirect(url_for(''index''))
    return render_template(''index.html'', form = form, name = session.get(''name''), known = session.get(''known'', False))

提交表单后,程序会使用filter_by()查询过滤器在数据库中查找提交的名字。变量known被写入用户会话中,因此重定向后,可以把数据传给模板,用来显示自定义的欢迎消息。

 

2、修改templates/index.html

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf%}

{% block title %}Flasky{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}</h1>
    {% if not known %}
    <p>Pleased to meet you!</p>
    {% else %}
    <p>Happy to see you again!</p>
    {% endif %}
</div>
{{ wtf.quick_form(form)}}
{% endblock %}

 

3、集成python shell

每次启动shell都要导入数据库实例和模型,为避免重复,下面命令可让Flask-Script的shell命令自动导入特点的对象

from flask_script import Manager,Shell

#为shell命令添加一个上下文
def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell", Shell(make_context=make_shell_context))

在次启动时,自动导入了模型

 

 

使用Flask-Migrate实现数据库的迁移

1、安装Flask-Migrate

 

 

2、在hello.py中配置Flask-Migrate

from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)
app.config[''SQLALCHEMY_DATABASE_URI''] = ''sqlite:///data.sqlite''
app.config[''SQLALCHEMY_COMMIT_ON_TEARDOWN''] = True
app.config["SECRET_KEY"] = "123456"
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command(''db'', MigrateCommand)

 

 3、在迁移前,使用init子命令创建迁移仓库

python hello.py db init

该命令会创建migrations文件夹,所有迁移脚本都会存放其中

 

 执行完之后的目录结构

 

 

4、创建迁移脚本

在Alembic中,数据库迁移用迁移脚本表示,有两个函数:

upgrade() 把迁移中的改动应用到数据库中

downgrad() 将改动删除

数据库可以重设到修改历史的任意一点

迁移操作分为:

     手动迁移,只是一个骨架,uograde()和downgrade()函数都是空的,开发者要使用Alembic提供的Operations对象指令实现具体操作

     自动迁移,会根据模型定义和数据库当前状态之间的差异生成upgrade()和downgrade()函数的内容

migrate子命令用来自动创建迁移脚本:

python hello.py db migrate -m "initial migration"

 

 

5、更新数据库

检查并修正好迁移脚本后,可以使用 db upgrade 命令将迁移应用到数据库中:

python hello.py db uograde

 

 

生成需求文件

pip freeze >requirements.txt

 

 

 

 在新的虚拟环境中创建完整副本

pip install -r requirements.txt

Flask 中使用 Flask-SQLAlchemy 查询数据库在数据库内容更新时无法实时返回

Flask 中使用 Flask-SQLAlchemy 查询数据库在数据库内容更新时无法实时返回

Flask 中使用 Flask-SQLAlchemy 查询数据库在数据库内容更新时无法实时返回 Flask-SQLAlchemy 版本 :2.3.2

"""python

from flask.ext.sqlalchemy import SQLAlchemy


class UnlockedAlchemy(SQLAlchemy):
    def apply_driver_hacks(self, app, info, options):
        if "isolation_level" not in options:
            options["isolation_level"] = "READ COMMITTED"
        return super(UnlockedAlchemy, self).apply_driver_hacks(app, info, options)

# db = SQLAlchemy()  # 源码中options没有isolation_level设置项, 弃用
db = UnlockedAlchemy()

"""

关于配置Flask-SQLAlchemy以使用Flask-Restless的多个数据库的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于23. Flask 操作Mysql数据库 - flask-sqlalchemy扩展、5.5 使用Flask-SQLAlchemy管理数据库、6、使用Flask-SQLAlchemy管理数据库和数据库的迁移、Flask 中使用 Flask-SQLAlchemy 查询数据库在数据库内容更新时无法实时返回的相关知识,请在本站寻找。

本文标签: