flask-sqlalchemy库

发布于:2024-03-11 ⋅ 阅读:(56) ⋅ 点赞:(0)

彩笔激流勇退。

1. 简介

ORM,对象关系映射。简单来说,ORM将数据库中的表与面向对象中的类建立了一种对应关系。这样,我们要操作数据库,表,记录就可以直接通过操作类或者类实例来完成。

SQLAlchemy 是目前python中最垃圾的 ORM框架, 功能全面, 使用复杂。

Flask-SQLAlchemy 是一个为 Flask 应用增加 SQLAlchemy 支持的扩展,把原本pymysql几句话就能搞定的事情整成抽象的,继承的,封装的,多态的更适合高级程序员体质的负离子保温杯。

抛开兼容性不谈,Flask-SQLAlchemy无疑是磨练程序员改bug的磨刀石,是检验程序员记忆能力的试金石,是凝结了人类精华的草酸钙结石。

常用字段类型

类型名 python接收类型 mysql生成类型 说明
Integer int int 整型
Float float float 浮点型
Numeric(5,2) decimal.Decimal decimal(5,2)
Boolean bool tinyint 整型,只占1个字节
Text str text 文本类型,最大64KB
LongText str longtext 文本类型,最大4GB
String str varchar 变长字符串,必须限定长度
Date datetime.date date 日期
DateTime datetime.datetime datetime 日期和时间
Time datetime.time time 时间
TIMESTAMP datetime.datetime TIMESTAMP 时间戳,可以用text(‘now()’)赋值

常用的字段选项

选项名 说明
primary_key True,则该字段为表的主键,默认自增
unique True,则这列设置唯一
nullable False,则这列设置非空
default 为这列设置默认值,不作用在数据库
server_default 值必须是字符串格式,作用在数据库
index True,则为这列创建索引,提高查询效率

如果没有给对应字段的类属性设置default参数, 且添加数据时也没有给该字段赋值, 则sqlalchemy会给该字段设置默认值 None。

常见命令

db.create_all() #创建所有表
db.drop_all() #删除所有表
2. 创建表

pip install pymysql

pip install flask-sqlalchemy

数据库URL(连接地址)格式: 协议名://用户名:密码@数据库IP:端口号/数据库名

main.py

​ 在下面代码中,我们使用了 with app.app_context(): 语句来确保当前应用实例的操作db.create_all() 是在flask应用上下文中被调用的。

from app import *
from models import User

@app.route('/',methods=['GET','POST'])
def login():
    print(db)
    return 'hello world'

if __name__ == '__main__':
    with app.app_context():
        db.create_all()#创建表
    app.run(host='0.0.0.0',port=9901,debug=1)

modules.py

表名默认为类名小写, 可以通过 __tablename__类属性 进行修改

from app import db

class User(db.Model):# User表
    __tablename__ = 't_user'
    id= db.Column(db.Integer,primary_key=True) # 必须要有主键存在
    name=db.Column(db.String(20),nullable=True)# 可空
    age=db.Column(db.SmallInteger)
    gender=db.Column(db.Boolean)
    birthday=db.Column(db.Date)

对应MySQL语句

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` smallint DEFAULT NULL,
  `gender` tinyint(1) DEFAULT NULL,
  `birthday` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

app.py

from flask import Flask,url_for,request,render_template,make_response,redirect,jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__) # 用本脚本名实例化Flask对象
# 设置数据库连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/test1'

# 是否追踪数据库修改(开启后会触发一些钩子函数)  一般不开启, 会影响性能
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# 是否显示底层执行的SQL语句
app.config['SQLALCHEMY_ECHO'] = True

# 初始化组件对象, 直接关联Flask应用
db = SQLAlchemy(app)
3. 数据表简单查询

在这里插入图片描述

user=User.query

说明
user.filter_by(id=1) 只能等值查询,使用=
user.filter(User.id==1) 条件查询,用==
use.filter 参数与运算符 说明
and_(User.id==1,User.age==99)
or_(User.id==1,User.age==99)
~(User.id==1)
!= None>>=
User.name.like('%a%') 模糊查询
User.id.in_((1,2,5)) 范围查询
User.id.between(1,3) [1,3]
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        user=User.query
        print(user)#显示sql语句, 返回Query对象
        print(user.all())#[<User 1>, <User 2>, <User 3>],每个元素都是models.User类型
        print(user.count()) #返回query中的Model对象数量
        print(user.filter_by(age=30,id=1)) #显示SQL语句, 返回Query对象,内部条件为交集
4. 映射查询 db.session.query

映射查询在SQLAlchemy中,可以通过session对象的query方法完成。

注意关键字书写顺序

db.session.query().filter().group_by().having().order_by().paginate().all()
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        query=db.session.query(User) #<class 'flask_sqlalchemy.query.Query'>
        print(query.filter(User.id>1).all())# [<User 2>, <User 3>]
        query2=db.session.query(User.id,User.name)
        print(query2.filter(User.age==99).all())# [(2, 'tom')]
    app.run(host='0.0.0.0',port=9901,debug=1)
5. 排序 order_by

from sqlalchemy import desc

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        query = db.session.query(User.id, User.name,User.age)
        print(query.order_by(User.age).all())  # 默认升序排序,asc()
        print(query.order_by(desc(User.age)).all())  # 降序排序
        print(query.order_by(User.age,User.id).all())  # 先排age,后排id
    app.run(host='0.0.0.0', port=9901, debug=1)# 看起来是一个阻塞函数
6. 聚合函数

数据库先添加一个age为30的记录。

from sqlalchemy import func

聚合函数 说明
count() 记录数量
sum() 加和总值
avg() 平均值
max() 最大值
min() 最小值
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        query = db.session.query(func.max(User.age),func.avg(User.age))
            #相当于 SELECT max(age) , avg(age) FROM t_user
        print(query.all())  # [(99, Decimal('51.0000'))]
    app.run(host='0.0.0.0', port=9901, debug=1)
7. 分组查询 group_by
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        query = db.session.query(func.count(User.id))
        print(query.group_by(User.age).all())  
        # [(2,), (1,), (1,)]
    app.run(host='0.0.0.0', port=9901, debug=1)
8. 增删改

flask开了debug模式,删除数据会导致main函数重新执行,给爷整笑了。

if __name__ == '__main__':
    with app.app_context():
        db.create_all()

        #更新
        u = db.session.query(User.id==1)# 查询主键为1的记录
        u.name="Jack"
        #db.session.rollback() 事务回滚,默认遇到错误自动回滚
        db.session.commit()# 事务提交

        #删除
        u2=db.session.query(User).filter(User.id==6).all() # User 模型的实例
        if len(u2)!=0:
            db.session.delete(u2[0])
            db.session.commit()  # 事务提交

        #增加
        u3=User(id=7,name="lihua",age=35,gender=1,birthday='2077-1-1')
        db.session.add(u3)
        #db.session.add_all([u1,u2,u3]) 一次添加多个
        db.session.commit()

    app.run(host='0.0.0.0', port=9901, debug=0)
    # debug=1时,上面的delete操作会执行多次
    # 大概是是检测到了文件变化重启了一次main函数???
9. 分页查询 paginate

分页查询不老老实实用limit,非要整个paginate装什么高大上。

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        pg=db.session.query(User).paginate(page=2,per_page=2)# QueryPagination object
        print(pg.items)#[<User 3>, <User 4>],当前页数据
        print(pg.pages) #3 ,一共三页
        for i in pg.iter_pages(): #迭代Pagination.iter_pages对象
            print(i)#1 2 3
    app.run(host='0.0.0.0', port=9901, debug=0)
10. 原生sql支持
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        statement=text('select * from t_user where id> :id').params(id=1)
        query=db.session.query(User).from_statement(statement)
        print(query.all())# [<User 2>, <User 3>, <User 4>, <User 7>]

        #最傻逼的地方来了,新版本下面语句不支持
        # statement2 = text('select max(id) as mmid,max(age) as mage from t_user where id> :id').params(id=2)
        # query2 = db.session.query('mmid','mage').from_statement(statement2)# sqlalchemy.exc.ArgumentError

        # 感觉不如直接pymysql
        sql=text('select max(id) as mmid,max(age) as mage from t_user where id> :id')
        result=db.session.execute(sql,{'id':2})# CursorResult object
        #print(result.fetchall())# [(7, 45)] 如果这里获取了,下面就获取不了,有点类似游标后移导致没数据读
        for i in result:
            print(i)# (7, 45)
    app.run(host='0.0.0.0', port=9901, debug=0)

参考

flask框架与mysql开发入门到实践 白菜爱科技


网站公告

今日签到

点亮在社区的每一天
去签到