python -- (Flask简介) --(五)

1. Flask-SQLAlchemy

安装
pip install flask-sqlalchemy

# 如果连接的是 mysql 数据库,需要安装 mysqldb
pip install flask-mysqldb
数据库连接设置
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'

# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True

在这里插入图片描述

常用的SQLAlchemy字段类型

在这里插入图片描述

常用的SQLAlchemy列选项

在这里插入图片描述

常用的SQLAlchemy关系选项

在这里插入图片描述

2. 数据库基本操作

  • 在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。
    • 会话用 db.session 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用 commit() 方法提交会话。
  • 在 Flask-SQLAlchemy 中,查询操作是通过 query 对象操作数据。
    • 最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。
定义模型
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    us = db.relationship('User', backref='role')

    #repr()方法显示一个可读字符串
    def __repr__(self):
        return 'Role:%s'% self.name
        
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64),unique=True)
    password = db.Column(db.String(64))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:%s'%self.name
模型中关联关系
class Role(db.Model):
	...
	#关键代码
	users = db.relationship('User', backref='role', lazy='dynamic')

class User(db.Model):
    ...
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
  • 其中realtionship描述了Role和User的关系。在此文中,第一个参数为对应参照的类"User"
  • 第二个参数backref为类User申明新属性的方法
  • 第三个参数lazy决定了什么时候SQLALchemy从数据库中加载数据
    • 如果设置为子查询方式(subquery),则会在加载完Role对象后,就立即加载与其关联的对象,这样会让总查询数量减少,但如果返回的条目数量很多,就会比较慢
      • 设置为 subquery 的话,role.users 返回所有数据列表
    • 另外,也可以设置为动态方式(dynamic),这样关联对象会在被使用的时候再进行加载,并且在返回前进行过滤,如果返回的对象数很多,或者未来会变得很多,那最好采用这种方式
      • 设置为 dynamic 的话,role.users 返回查询对象,并没有做真正的查询,可以利用查询对象做其他逻辑,比如:先排序再返回结果
SQLAlchemy查询过滤器

在这里插入图片描述

SQLAlchemy查询执行器

在这里插入图片描述

创建表
db.create_all()
删除表
db.drop_all()
查询
  • filter_by精确查询
# 返回名字等于wang的所有人
User.query.filter_by(name='wang').all()
  • first()返回查询到的第一个对象
User.query.first()
  • all()返回查询到的所有对象
User.query.all()
  • filter模糊查询
# 返回名字结尾字符为g的所有数据
User.query.filter(User.name.endswith('g')).all()
  • get():参数为主键,如果主键不存在没有返回内容
User.query.get()
  • 逻辑非
# 返回名字不等于wang的所有数据
User.query.filter(User.name!='wang').all()
  • not_ 相当于取反
from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()
  • 逻辑与,需要导入and,返回and()条件满足的所有数据
from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
  • 逻辑或,需要导入or_
from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
  • 查询数据后删除
user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()
  • 更新数据
user = User.query.first()
user.name = 'dong'
db.session.commit()
User.query.first()
  • 查询角色的所有用户
#查询roles表id为1的角色
ro1 = Role.query.get(1)
#查询该角色的所有用户
ro1.us.all()
  • 查询用户所属角色
#查询users表id为3的用户
us1 = User.query.get(3)
#查询用户属于什么角色
us1.role
示例演练
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://information:information@127.0.0.1:3306/information'
# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True

db = SQLAlchemy(app)


# 角色  1的一方
class Role(db.Model):
    # 指定该模型对应数据库中的表名,如果不指定为类名小写
    __tablename__ = "roles"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    # backref 在这行代码的作用是,给前面的 User 添加一个属性,名字叫backref的值
    # 以便可以直接通过 user.role 方法到一的一方的数据
    users = db.relationship('User', backref='role')

    def __repr__(self):
        return 'Role %d %s' % (self.id, self.name)


# 用户  多的一方
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64),unique=True)
    password = db.Column(db.String(64))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:%s'%self.name


@app.route('/')
def index():
    return 'index'


if __name__ == '__main__':
    db.drop_all()
    db.create_all()

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

    us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id)
    us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id)
    us5 = User(name='tang', email='tang@qq.com', password='158104', role_id=ro2.id)
    us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id)
    us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id)
    us8 = User(name='liu', email='liu@qq.com', password='867322', role_id=ro1.id)
    us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id)
    us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id)
    db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
    db.session.commit()

    app.run(debug=True)

    """
    查询所有用户数据
        User.query.all()
    查询有多少个用户
        User.query.count()
    查询第1个用户
        User.query.first()
    查询id为4的用户[3种方式]
        User.query.get(4)
        User.query.filter_by(id=4).first()
        User.query.filter(User.id == 4).first()
    查询名字结尾字符为g的所有数据[startswith/包含contains]
        User.query.filter(User.name.endswith('g')).all()
    查询名字不等于wang的所有数据[2种方式]
        User.query.filter(not_(User.name == 'wang')).all()
        User.query.filter(User.name != 'wang').all()
    查询名字和邮箱都以 li 开头的所有数据[2种方式]
        User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all()
        User.query.filter(and_(User.name.startswith('li'), User.email.startswith('li'))).all()
    查询password是 `123456` 或者 `email` 以 `163.com` 结尾的所有数据
        User.query.filter(or_(User.passwd == '123456', User.email.endswith('163.com))).all()
    查询id为 [1, 3, 5, 7, 9] 的用户列表
        User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all
    查询name为liu的角色数据
        User.query.filter(User.name == 'liu').first().role
    查询所有用户数据,并以邮箱排序
        User.query.order_by(User.email).all()
    每页3个,查询第2页的数据
        paginate = User.query.paginate(2, 3)    第一个参数代表查询第几页,第二个参数代表每页几个
        paginate.items  当前页数据
        paginate.pages  总页数
        paginate.page   当前页  
    """

3. 数据库迁移

环境
pip install flask-migrate
示例代码
from flask import Flask
from flask_migrate import Migrate, MigrateCommand
# MigrateCommand 迁移命令
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.secret_key = 'aaasas'

# 设置连接数据
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://information:information@127.0.0.1:3306/information'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

# 实例化SQLAlchemy对象
db = SQLAlchemy(app)


# 使用迁移类将应用和数据库连接对象保存起来
Migrate(app, db)
# 创建终端命令的对象
manager = Manager(app)
# 将数据库的迁移命令添加到manager中
manager.add_command('aaa', MigrateCommand)


# 定义模型Role
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    user = db.relationship('User', backref='role')

    # repr()方法显示一个可读字符串,
    def __repr__(self):
        return 'Role:'.format(self.name)


# 定义用户
class User(db.Model):
    __talbe__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    #设置外键
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:'.format(self.username)


if __name__ == '__main__':
    manager.run()
创建迁移脚本
  • 自动创建迁移脚本有两个函数
    • upgrade():函数把迁移中的改动应用到数据库中。
    • downgrade():函数则将改动删除。
  • 自动创建的迁移脚本会根据模型定义和数据库当前状态的差异,生成upgrade()和downgrade()函数的内容。
  • 对比不一定完全正确,有可能会遗漏一些细节,需要进行检查
迁移操作:
1.python 文件 db init
2.python 文件 db migrate -m"版本名(注释)"
3.python 文件 db upgrade 然后观察表结构
4.根据需求修改模型
5.python 文件 db migrate -m"新版本名(注释)"
6.python 文件 db upgrade 然后观察表结构
7.若返回版本,则利用 python 文件 db history查看版本号
8.python 文件 db downgrade(upgrade) 版本号

---------------------------------------------------END-----------------------------------------------
---------------------------------------------------END-----------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值