1、安装sqlalchemy,Wind+R,输入以下命令。
官网连接
pip install Flask-SQLAlchemy
2、连接mysql数据库,安装flask-mysqldb
pip install flask-mysqldb
3、导入Flask-SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
使用Flask-SQLAlchemy扩展操作数据库,首先需要通过URL建立数据库连接,必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI中。
# 第一种方式:
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://<帐号>:<密码>@:3306/<数据库名称>'
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@127.0.0.1:3306/db_python04'
# 第二种方式:
SQL_CONFIG = {
'host': 'localhost',
'port': '3306',
'user': 'root',
'password': '',
'database': 'flaskdb',
}
SQLALCHEMY_DATABASE_URI = 'mysql://%s:%s@%s:%s/%s' % (
SQL_CONFIG['user'], SQL_CONFIG['password'],
SQL_CONFIG['host'], SQL_CONFIG['port'],
SQL_CONFIG['database']
)
SQLALCHEMY_TRACK_MODIFICATIONS = True
app.config['SQLALCHEMY_ECHO'] = True
名字 | 备注 |
---|---|
SQLALCHEMY_DATABASE_URI | 用于连接的数据库 URI 。例如:sqlite:////tmp/test.dbmysql://username:password@server/d |
SQLALCHEMY_BINDS | 一个映射 binds 到连接 URI 的字典。更多 binds 的信息见用 Binds 操作多个数据库。 |
SQLALCHEMY_ECHO | 如果设置为Ture, SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有有帮助。 |
SQLALCHEMY_RECORD_QUERIES | 可以用于显式地禁用或者启用查询记录。查询记录 在调试或者测试模式下自动启用。更多信息请参阅 get_debug_queries()。 |
SQLALCHEMY_NATIVE_UNICODE | 可以用于显式地禁用支持原生的 unicode。这是 某些数据库适配器必须的(像在 Ubuntu 某些版本上的 PostgreSQL),当使用不合适的指定无编码的数据库 默认值时。 |
SQLALCHEMY_POOL_SIZE | 数据库连接池的大小。默认是数据库引擎的默认值 (通常是 5)。 |
SQLALCHEMY_POOL_TIMEOUT | 指定数据库连接池的超时时间。默认是 10。 |
SQLALCHEMY_POOL_RECYCLE | 自动回收连接的秒数。这对 MySQL 是必须的,默认 情况下 MySQL 会自动移除闲置 8 小时或者以上的连接。 需要注意地是如果使用 MySQL 的话, Flask-SQLAlchemy 会自动地设置这个值为 2 小时。 |
SQLALCHEMY_MAX_OVERFLOW | 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。 |
SQLALCHEMY_TRACK_MODIFICATIONS | 如果设置成 True (默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。 |
# 创建数据库sqlalchemy模型对象
db = SQLAlchemy(app)
class Role(db.Model):
"""
用户角色/身份表
"""
__tablename__ = 'tbl_roles'
id = db.Column(db.BIGINT, primary_key=True, nullable=False, autoincrement=True)
# 身份名称(不可重复)
name = db.Column(db.String(32), unique=True)
# 反向映射外键,模型类,不存在的方便查询用,backref反推拿到的不只是role_id,而是整条记录
users = db.relationship('User', backref='role')
def __repr__(self):
"""定义后显示对象更直观"""
return "Role object:name=%s" % self.name
class User(db.Model):
"""
用户表
"""
__tablename__ = 'tbl_users' # 指明数据库的表名
id = db.Column(db.BIGINT, primary_key=True) # 设置为主键
name = db.Column(db.String(32), unique=True) # Column列
email = db.Column(db.String(64), unique=True)
age = db.Column(db.Integer)
gender = db.Column(db.Boolean)
account = db.Column(db.String(32), unique=True)
password = db.Column(db.String(128))
# 映射外键
role_id = db.Column(db.BIGINT, db.ForeignKey('tbl_roles.id'))
def __repr__(self):
return "User object:name=%s" % self.name
# 清除数据库中所有数据,工作时不要清除数据库
db.drop_all()
# 创建所有表
db.create_all()
# 创建对象
role1 = Role(name="xiaoming")
# session记录对象任务
db.session.add(role1)
# 提交任务到数据库中
db.session.commit()
"""
添加数据的方法
"""
# 1.增加数据库数据(增加用户)
db.session.add_all([
User(name='张三', age=18, gender=0, account='zhang3', password='123456', role_id=1, email="[email protected]"),
User(name='李四', age=20, gender=1, account='li4', password='123456', role_id=2, email="[email protected]"),
User(name='王五', age=18, gender=1, account='wang5', password='159357', role_id=2, email="[email protected]"),
User(name='赵六', age=21, gender=1, account='zhao6', password='159357', role_id=1, email="[email protected]"),
])
db.session.commit()
# 2.添加数据库数据
us1 = User(name='赵六', age=21, gender=1, account='zhao6', password='159357', role_id=4)
us2 = User(name='王五', age=18, gender=1, account='wang5', password='159357', role_id=3)
# 一次添加多条数据用列表
db.session.add_all([us1, us2])
db.session.commit()
"""
查询数据的方法:
"""
# 一.通过sqlalchemy封装的方法查询所有数据
r1 = Role.query.all()
print(r1)
# 1.查询第一条记录角色
lis1 = Role.query.first()
print(lis1)
# 获取第一条记录中的属性值
print(lis1.name)
# 2.get方法只能根据主键id值进行查询,
#查询roles表id为2的角色
lis2 = Role.query.get(2)
print(lis2)
print(lis2.name)
# 二.通过sqlalchemy原始的方法查询所有数据
r2 = db.session.query(Role).all
print(r2)
lis3 = db.session.query(Role).first()
print(lis3)
print(lis3.name)
lis4 = db.session.query(Role).get(2)
print(lis4)
print(lis4.name)
eg:角色和用户的关系是一对多,一个角色可以有多个用户,一个用户只能属于一个角色。
#查询角色所属的用户
#查询角色表id为2的角色
lis2 = Role.query.get(2)
print(lis2)
#查询用户所属角色
User10 = User.query.get(3)
print(User10.role)
from sqlalchemy import or_
from sqlalchemy import fun
# 通过filter_by()方法进行and条件筛选信息
print(User.query.filter_by(name="王五").all())
user1 = User.query.filter_by(name="王五").first()
print(user1.age)
print(User.query.filter_by(name="王五", role_id=3).first()) # 两个条件是and关系
user2 = User.query.filter_by(name="王五", role_id=1).first() # 若查询不到,不会出现异常,是NoneType类型
print(type(user2))
# 通过filter()方法筛选or条件信息
user3 = User.query.filter(User.name == "王五", User.role_id == 1).all()
print(user3)
# 通过导入or_函数筛选or条件信息
user4 = User.query.filter(or_(User.name == "王五", User.role_id == 1)).all()
print(user4)
user5 = User.query.filter(or_(User.name == "王五", User.email.endswith("126.com"))).all()
print(user5)
print(user5[0].name) # 获取满足以上两个条件中的一个条件的姓名
# User.query.filter().offset().limit().order_by().all()
# 跳过一条从第二条开始取offset偏移
user6 = User.query.offset(1).all
print(user6)
print(user6[0].name)
print()
# 排序/降序
print(User.query.order_by("id").all()) # asc升序可省略
print(User.query.order_by(User.id.desc()).all())
# 分组/求和
print(db.session.query(User.role_id).group_by(User.role_id).all())
user7 = db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id).all()
print(user7)
"""
更新/修改记录属性值
"""
# 先读出来,再修改属性,方法一:
user8 = User.query.get(1)
print(user8.name)
user8.name = "小红"
db.session.add(user8)
db.session.commit()
# 不需要读,直接修改属性,方法二:
User.query.filter_by(name="李四").update({"name": "小明"}) # 已键值对的形式进行修改
db.session.commit()
""""
删除记录
"""
# user9 = User.query.get(3)
# db.session.delete(user9)
# db.session.commit()
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import or_
from sqlalchemy import func
app = Flask(__name__)
class Config(object):
"""配置参数"""
# 数据被修改时,修改模型类,设置sqlalchemy自动更新跟踪数据库
SQLALCHEMY_TRACK_MODIFICATIONS = True
# 设置sqlalchemy配置参数
# 第一种方式:
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://<帐号>:<密码>@:3306/<数据库名称>'
# SQLALCHEMY_DATABASE_URI = 'mysql://root:@127.0.0.1:3306/db_python04'
# 第二种方式:
SQL_CONFIG = {
'host': 'localhost',
'port': '3306',
'user': 'root',
'password': '',
'database': 'flaskdb',
}
SQLALCHEMY_DATABASE_URI = 'mysql://%s:%s@%s:%s/%s' % (
SQL_CONFIG['user'], SQL_CONFIG['password'],
SQL_CONFIG['host'], SQL_CONFIG['port'],
SQL_CONFIG['database']
)
app.config.from_object(Config)
# 查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True
# 创建数据库sqlalchemy模型对象
db = SQLAlchemy(app)
# 表名命名方式
# 第一种:数据库名缩写_表名 flaskdb fl_user
# 第二种:tbl_表名 table_user
class Role(db.Model):
"""
用户角色/身份表
"""
__tablename__ = 'tbl_roles'
id = db.Column(db.BIGINT, primary_key=True, nullable=False, autoincrement=True)
# 身份名称(不可重复)
name = db.Column(db.String(32), unique=True)
# 反向映射外键,模型类,不存在的方便查询用,backref反推拿到的不只是role_id,而是整条记录
users = db.relationship('User', backref='role')
def __repr__(self):
"""定义后显示对象更直观"""
return "Role object:name=%s" % self.name
class User(db.Model):
"""
用户表
"""
__tablename__ = 'tbl_users' # 指明数据库的表名
id = db.Column(db.BIGINT, primary_key=True) # 设置为主键
name = db.Column(db.String(32), unique=True) # Column列
email = db.Column(db.String(64), unique=True)
age = db.Column(db.Integer)
gender = db.Column(db.Boolean)
account = db.Column(db.String(32), unique=True)
password = db.Column(db.String(128))
# 映射外键
role_id = db.Column(db.BIGINT, db.ForeignKey('tbl_roles.id'))
def __repr__(self):
return "User object:name=%s" % self.name
@app.route("/")
def index():
return "index page"
if __name__ == '__main__':
# 清除数据库种所有数据
db.drop_all()
# 创建所有表
db.create_all()
"""
创建角色方法:
"""
# 增加数据库数据(创建角色)
db.session.add(Role(name='本科生'))
db.session.add(Role(name='研究生'))
db.session.add(Role(name='博士生'))
db.session.add(Role(name='宿管'))
db.session.add(Role(name='讲师'))
db.session.add(Role(name='副教授'))
db.session.add(Role(name='教授'))
# # 创建对象
# role1 = Role(name="xiaoming")
# # session记录对象任务
# db.session.add(role1)
# # 提交任务到数据库中
db.session.commit()
"""
添加数据的方法
"""
# 1.增加数据库数据(增加用户)
db.session.add_all([
User(name='张三', age=18, gender=0, account='zhang3', password='123456', role_id=1, email="[email protected]"),
User(name='李四', age=20, gender=1, account='li4', password='123456', role_id=2, email="[email protected]"),
User(name='王五', age=18, gender=1, account='wang5', password='159357', role_id=2, email="[email protected]"),
User(name='赵六', age=21, gender=1, account='zhao6', password='159357', role_id=1, email="[email protected]"),
])
db.session.commit()
# 2.添加数据库数据
# us1 = User(name='赵六', age=21, gender=1, account='zhao6', password='159357', role_id=4)
# us2 = User(name='王五', age=18, gender=1, account='wang5', password='159357', role_id=3)
# 一次添加多条数据用列表
# db.session.add_all([us1, us2])
# db.session.commit()
"""
查询数据的方法:
"""
# 一.通过sqlalchemy封装的方法查询所有数据
r1 = Role.query.all()
print(r1)
# 1.查询第一条记录角色
lis1 = Role.query.first()
print(lis1)
# 获取第一条记录中的属性值
print(lis1.name)
# 2.get方法只能根据主键id值进行查询
lis2 = Role.query.get(2)
print(lis2)
print(lis2.name)
# 二.通过sqlalchemy原始的方法查询所有数据
r2 = db.session.query(Role).all
print(r2)
lis3 = db.session.query(Role).first()
print(lis3)
print(lis3.name)
lis4 = db.session.query(Role).get(2)
print(lis4)
print(lis4.name)
# 通过filter_by()方法进行and条件筛选信息
print(User.query.filter_by(name="王五").all())
user1 = User.query.filter_by(name="王五").first()
print(user1.age)
print(User.query.filter_by(name="王五", role_id=3).first()) # 两个条件是and关系
user2 = User.query.filter_by(name="王五", role_id=1).first() # 若查询不到,不会出现异常,是NoneType类型
print(type(user2))
# 通过filter()方法筛选or条件信息
user3 = User.query.filter(User.name == "王五", User.role_id == 1).all()
print(user3)
# 通过导入or_函数筛选or条件信息
user4 = User.query.filter(or_(User.name == "王五", User.role_id == 1)).all()
print(user4)
user5 = User.query.filter(or_(User.name == "王五", User.email.endswith("126.com"))).all()
print(user5)
print(user5[0].name) # 获取满足以上两个条件中的一个条件的姓名
# User.query.filter().offset().limit().order_by().all()
# 跳过一条从第二条开始取offset偏移
user6 = User.query.offset(1).all
print(user6)
print(user6[0].name)
print()
# 排序/降序
print(User.query.order_by("id").all()) # asc升序可省略
print(User.query.order_by(User.id.desc()).all())
# 分组/求和
print(db.session.query(User.role_id).group_by(User.role_id).all())
user7 = db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id).all()
print(user7)
"""
更新/修改记录属性值
"""
# 先读出来,再修改属性,方法一:
user8 = User.query.get(1)
print(user8.name)
user8.name = "小红"
db.session.add(user8)
db.session.commit()
# 不需要读,直接修改属性,方法二:
User.query.filter_by(name="李四").update({"name": "小明"}) # 已键值对的形式进行修改
db.session.commit()
""""
删除记录
"""
# user9 = User.query.get(3)
# db.session.delete(user9)
# db.session.commit()
以下笔记来自于此链接:记得点开后给个star哦
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
"""
配置
"""
class Config:
DEBUG = True
SQL_CONFIG = {
'host': 'localhost',
'port': '3306',
'user': 'root',
'password': '',
'database': 'flaskdb',
}
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://<帐号>:<密码>@:3306/<数据库名称>'
SQLALCHEMY_DATABASE_URI = 'mysql://' + \
SQL_CONFIG['user'] + ':' + \
SQL_CONFIG['password'] + '@' + \
SQL_CONFIG['host'] + ':' + \
SQL_CONFIG['port'] + '/' + \
SQL_CONFIG['database']
# 数据被修改时,修改模型类
SQLALCHEMY_TRACK_MODIFICATIONS = True
# 打印SQL语句
SQLALCHEMY_ECHO = True
app.config.from_object(Config)
"""
数据库模型
"""
db = SQLAlchemy(app)
class Role(db.Model):
"""
用户角色/身份表
"""
__tablename__ = 'tbl_roles'
id = db.Column(db.BIGINT, primary_key=True, nullable=False, autoincrement=True)
# 身份名称(不可重复)
name = db.Column(db.String(32), unique=True)
# 反向映射外键,模型类,不存在的方便查询用,backref反推拿到的不只是role_id,而是整条记录
users = db.relationship('User', backref='role')
class User(db.Model):
"""
用户表
"""
__tablename__ = 'tbl_users'
id = db.Column(db.BIGINT, primary_key=True)
name = db.Column(db.String(32))
age = db.Column(db.Integer)
gender = db.Column(db.Boolean)
account = db.Column(db.String(32), unique=True)
password = db.Column(db.String(128))
# 映射外键
role_id = db.Column(db.BIGINT, db.ForeignKey('tbl_roles.id'))
"""
接口
"""
def return_html_table(aoa_table, thead=None, title=''):
"""
返回可视化列表
:param aoa_table: 在网页中展示的表格
:param thead: 表格标题(可选)
:param title: 标题(可选)
:return:
"""
buffer = []
buffer.append("""""")
buffer.append(''
)
buffer.append(title)
buffer.append('')
buffer.append('')
# Head
if thead is not None:
buffer.append('')
for item in thead:
buffer.append('')
buffer.append(str(item))
buffer.append(' ')
buffer.append(' ')
# Body
buffer.append('')
for line in aoa_table:
buffer.append('')
for item in line:
buffer.append('')
buffer.append(str(item))
buffer.append(' ')
buffer.append(' ')
buffer.append('')
buffer.append('
')
return ''.join(buffer), 200, {'Content-Type': 'text/html; Charset=utf-8'}
@app.route("/")
def index():
return """
"""
@app.route("/add_one_user")
def add_one_user():
random_names = ['赵', '钱', '孙', '李']
import random
r = random.randint(0, 3)
name = random_names[r] + str(r * 36 + r / 3 + random.randint(0, 99) / 7)
db.session.add(User(
name=name,
age=random.randint(0, 99),
gender=random.randint(0, 1),
account=name,
password=random.randint(100000, 999999),
role_id=random.randint(1, 7)))
db.session.commit()
return '新增用户: ' + name
@app.route("/update_message")
def update_message():
User.query.filter_by(gender=0).update({'password': '000000'})
db.session.commit()
return 'gender=0的用户密码变为000000'
@app.route("/delete_user")
def delete_user():
item = User.query.first()
db.session.delete(item)
db.session.commit()
return '删除用户:' + item.name
@app.route("/read_all_role")
def read_all_role():
dat_all = Role.query.all()
buffer = []
for item in dat_all:
buffer.append([item.id, item.name])
return return_html_table(buffer, ['id', 'name'], '读取全部Role')
@app.route("/read_all_user")
def read_all_user():
dat_all = User.query.all()
buffer = []
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password])
return return_html_table(buffer,
['id', 'name', 'age', 'gender', 'account', 'password'],
'读取全部User')
@app.route("/read_order_role")
def read_order_role():
dat_all = Role.query.order_by(Role.id.desc()).all()
buffer = []
for item in dat_all:
buffer.append([item.id, item.name])
return return_html_table(buffer, ['id', 'name'], '读取全部Role,以id降序(desc)排序')
@app.route("/read_limit_user")
def read_limit_user():
buffer = []
buffer.append(['取头2条'])
dat_all = User.query.limit(2).all()
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password])
buffer.append(['跳过2条,再取2条'])
dat_all = User.query.offset(2).limit(2).all()
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password])
return return_html_table(buffer,
['id', 'name', 'age', 'gender', 'account', 'password'],
'读取User、每次读2条')
@app.route("/read_first_role")
def read_first_role():
item = Role.query.first()
return return_html_table([[item.id, item.name]], ['id', 'name'], '读取第一条Role')
@app.route("/read_by_id_role")
def read_by_id_role():
item = Role.query.get(1)
return return_html_table([[item.id, item.name]], ['id', 'name'], '读取Role中ID为1的数据')
@app.route("/read_filter_from_user")
def read_filter_from_user():
from sqlalchemy import or_, and_
dat_all = User.query.filter(User.age == 18, User.gender == 1)
# dat_all = User.query.filter(or_(User.age == 18, User.gender == 1))
# dat_all = User.query.filter(and_(User.age == 18, User.gender == 1))
buffer = []
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password])
return return_html_table(buffer,
['id', 'name', 'age', 'gender', 'account', 'password'],
'读取User表中 age==18 的数据')
@app.route("/read_filter_by_from_user")
def read_filter_by_from_user():
dat_all = User.query.filter_by(gender=0, age=18)
buffer = []
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password])
return return_html_table(buffer,
['id', 'name', 'age', 'gender', 'account', 'password'],
'读取User表中 age=18、gender=0 的数据')
@app.route("/read_group")
def read_group():
from sqlalchemy import func
query = db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id)
dat_all = query.all()
buffer = []
for line in dat_all:
line_buffer = []
for item in line:
line_buffer.append(item)
buffer.append(line_buffer)
return return_html_table(buffer, ['role_id', 'count'], title='分组查询')
@app.route("/read_relation")
def read_relation():
# 因为 backref 的设置
dat_all = User.query.all()
buffer = []
for item in dat_all:
buffer.append([item.id, item.name, item.age, item.gender, item.account, item.password, item.role.name])
return return_html_table(buffer,
['id', 'name', 'age', 'gender', 'account', 'password', 'role'],
'间接读取另一张表,获得角色名称')
"""
运行
"""
def db_while_first_run():
"""
本方法用于初始化数据库
:return:
"""
# 根据模型创建数据库表
db.create_all()
# 增加数据库数据(创建角色)
db.session.add(Role(name='本科生'))
db.session.add(Role(name='研究生'))
db.session.add(Role(name='博士生'))
db.session.add(Role(name='宿管'))
db.session.add(Role(name='讲师'))
db.session.add(Role(name='副教授'))
db.session.add(Role(name='教授'))
db.session.commit()
# 增加数据库数据(增加用户)
db.session.add_all([
User(name='张三', age=18, gender=0, account='zhang3', password='123456', role_id=1),
User(name='李四', age=20, gender=1, account='li4', password='123456', role_id=2),
User(name='王五', age=18, gender=1, account='wang5', password='159357', role_id=3),
User(name='赵六', age=21, gender=1, account='zhao6', password='159357', role_id=4),
])
db.session.commit()
# 清除数据库所有内容
# db.drop_all()
if __name__ == '__main__':
from sqlalchemy.exc import ProgrammingError
try:
result = Role.query.all()
print(len(result))
except ProgrammingError:
print("读取数据库异常")
print("尝试创建数据库")
db_while_first_run()
# end try
app.run()