flask-sqlalchemy库

彩笔激流勇退。

1. 简介

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

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

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

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

常用字段类型

类型名python接收类型mysql生成类型说明
Integerintint整型
Floatfloatfloat浮点型
Numeric(5,2)decimal.Decimaldecimal(5,2)
Booleanbooltinyint整型,只占1个字节
Textstrtext文本类型,最大64KB
LongTextstrlongtext文本类型,最大4GB
Stringstrvarchar变长字符串,必须限定长度
Datedatetime.datedate日期
DateTimedatetime.datetimedatetime日期和时间
Timedatetime.timetime时间
TIMESTAMPdatetime.datetimeTIMESTAMP时间戳,可以用text(‘now()’)赋值

常用的字段选项

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

如果没有给对应字段的类属性设置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开发入门到实践 白菜爱科技

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/444525.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UDP与TCP:了解这两种网络协议的不同之处

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

探索stable diffusion的奇妙世界--01

目录 1. 理解prompt提示词&#xff1a; 2. Prompt中的技术参数&#xff1a; 3. Prompt中的Negative提示词&#xff1a; 4. Prompt中的特殊元素&#xff1a; 5. Prompt在stable diffusion中的应用&#xff1a; 6. 作品展示&#xff1a; 在AI艺术领域&#xff0c;stable di…

Linux的进程调度实现

经常被问到进程的调度算法有哪些&#xff0c;什么先进先出、短进程优先、时间片轮转、多级反馈多列等等算法能说一大堆&#xff1f;那具体的&#xff0c;linux内核使用了什么样的算法&#xff0c;且来探究一下。 本文所引用源码基于linux内核2.6.34版本。 目录 调度器类 从 s…

LLM Drift(漂移), Prompt Drift Cascading(级联)

原文地址&#xff1a;LLM Drift, Prompt Drift & Cascading 提示链接可以手动或自动执行&#xff1b;手动需要通过 GUI 链构建工具手工制作链。自治代理在执行时利用可用的工具动态创建链。这两种方法都容易受到级联、LLM 和即时漂移的影响。 2024 年 2 月 23 日 在讨论大型…

STM32_3-1点亮LED灯与蜂鸣器发声

STM32之GPIO GPIO在输出模式时可以控制端口输出高低电平&#xff0c;用以驱动Led蜂鸣器等外设&#xff0c;以及模拟通信协议输出时序等。 输入模式时可以读取端口的高低电平或电压&#xff0c;用于读取按键输入&#xff0c;外接模块电平信号输入&#xff0c;ADC电压采集灯 GP…

记一次项目所学(中间件等)-动态提醒功能(RocketMQ)

记一次项目所学(中间件等&#xff09;–动态提醒功能&#xff08;RocketMQ&#xff09; 订阅发布模式与观察者模式 RocketMQ&#xff1a;纯java编写的开源消息中间件 高性能低延迟分布式事务 Redis : 高性能缓存工具&#xff0c;数据存储在内存中&#xff0c;读写速度非常快 …

读算法的陷阱:超级平台、算法垄断与场景欺骗笔记05_共谋(中)

1. 默许共谋 1.1. 又称寡头价格协调&#xff08;Oligopolistic Price Coordination&#xff09;或有意识的平行行为&#xff08;Conscious Parallelism&#xff09; 1.1.1. 在条件允许的情况下&#xff0c;它会发生在市场集中度较高的行业当中 1.1.…

AI智能应用百科立即落地实操课

该课程旨在教授学员如何将AI智能应用于实际场景。通过深入的案例研究和实操练习&#xff0c;学员将学会应用机器学习、自然语言处理等技术&#xff0c;快速解决现实问题。课程强调实际操作&#xff0c;帮助学员快速运用AI技术解决工作中的挑战。 课程大小&#xff1a;3.3G 课…

(关键点检测)YOLOv8实现多类人体姿态估计的输出格式分析

&#xff08;关键点检测&#xff09;YOLOv8实现多类人体姿态估计的输出格式分析 任务分析 所使用的数据配置文件 网络结构 导出模型 用 netron 可视化 输出格式分析 参考链接 1. 任务分析 判断人体关键点时一并给出关键点所属的类别&#xff0c;比如男人&#xff0c;女…

Vue3 状态管理 - Pinia

Vue3 状态管理 - Pinia 1. 什么是Pinia Pinia 是 Vue 的专属的最新状态管理库 &#xff0c;是 Vuex 状态管理工具的替代品 2. 手动添加Pinia到Vue项目 后面在实际开发项目的时候&#xff0c;Pinia可以在项目创建时自动添加&#xff0c;现在我们初次学习&#xff0c;从零开…

EasyPoi 教程

文章目录 EasyPoi教程文档1. 前传1.1 前言 这个服务即将关闭,文档迁移到 http://www.wupaas.com/ 请大家访问最新网站1.2 Easypoi介绍1.3 使用1.4 测试项目1.5 可能存在的小坑 2. Excel 注解版2.1 Excel导入导出2.2 注解注解介绍ExcelTargetExcelEntityExcelCollectionExcelIgn…

[LeetCode][LCR151]彩灯装饰记录 III——队列

题目 LCR 151. 彩灯装饰记录 III 一棵圣诞树记作根节点为 root 的二叉树&#xff0c;节点值为该位置装饰彩灯的颜色编号。请按照如下规则记录彩灯装饰结果&#xff1a; 第一层按照从左到右的顺序记录除第一层外每一层的记录顺序均与上一层相反。即第一层为从左到右&#xff0c…

transformer--使用transformer构建语言模型

什么是语言模型? 以一个符合语言规律的序列为输入&#xff0c;模型将利用序列间关系等特征&#xff0c;输出一个在所有词汇上的概率分布.这样的模型称为语言模型. # 语言模型的训练语料一般来自于文章&#xff0c;对应的源文本和目标文本形如: src1"Ican do",tgt1…

KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记10 - STM32的SDIO学习2

KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记10 - STM32的SDIO学习2 一、问题回顾二、本次的任务三、 需要注意的问题3.1 Card Identification Mode时的时钟频率3.2 CMD0指令的疑似问题3.3 发送带参数的ACMD41时要注意时间时序和时效3.4 CPSM的指令发送问题3.5 调试过程中的SD卡的…

分布式解决方案

目录 1. 分布式ID1-1. 传统方案1-2. 分布式ID特点1-3. 实现方案1-4. 开源组件 1. 分布式ID 1-1. 传统方案 时间戳UUID 1-2. 分布式ID特点 全局唯一高并发高可用 1-3. 实现方案 方案总结&#xff1a; 号段模式 有两台服务器&#xff0c;给第一台服务器分配0-100&#xff0…

嵌入式Linux串口和 poll() 函数的使用

一、poll() 函数的介绍 poll() 函数用于监控多个文件描述符的变化的函数。它可以用来检查一个或多个文件描述符的状态是否改变&#xff0c;比如是否可读、可写或有错误发生。它常用于处理 I/O 多路复用&#xff0c;这在需要同时处理多个网络连接或文件操作时非常有用。 头文件…

Linux高级IO之select

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、五种IO模型 1.IO效率的问题 2.阻塞IO是…

蓝桥杯C/C++实用知识总结

蓝桥杯C/C 文章目录 蓝桥杯C/C头文件实用函数及运算符求幂次移位运算符STL排序sort()函数依次读取数据STL全排列函数next_permutation()求数组最大/最小值初始化函数memset()GCD(最大公约数)和LCM&#xff08;最小公倍数&#xff09;C字符串函数 实用数据结构模板vector链表lis…

未来城市:探索数字孪生在智慧城市中的实际应用与价值

目录 一、引言 二、数字孪生与智慧城市的融合 三、数字孪生在智慧城市中的实际应用 1、智慧交通管理 2、智慧能源管理 3、智慧建筑管理 4、智慧城市管理 四、数字孪生在智慧城市中的价值 五、挑战与展望 六、结论 一、引言 随着科技的飞速发展&#xff0c;智慧城市已…

鸿蒙OpenHarmony HDF 驱动开发

目录 序一、概述二、HDF驱动框架三、驱动程序四、驱动配置坚持就有收获 序 最近忙于适配OpenHarmonyOS LiteOS-M 平台&#xff0c;已经成功实践适配平台GD32F407、STM32F407、STM32G474板卡&#xff0c;LiteOS适配已经算是有实际经验了。 但是&#xff0c;鸿蒙代码学习进度慢下…