【Flask框架】——27 SQLAlchemy高级

news2024/10/6 6:00:04

在这里插入图片描述

在这里插入图片描述


1、排序

  1. order_by方法排序:可以指定根据模型中某个属性进行排序,"模型名.属性名.desc()"代表的是降序排序。
# 根据年龄降序
lst = session.query(Student).order_by(Student.age.desc()).all()
# 根据年龄升序
lst = session.query(Student).order_by(Student.age).all()
  1. 在定义模型的时候指定排序:有些时候,不想每次在查询的时候都用order_by方法,可以在定义模型的时候就指定排序的方式。

一、模型对象定义中加排序

# 学生表
class Student(Base):
    __tablename__ = 't_student'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50))
    age = Column(Integer)

    # 4.定义relationship属性
    course_list = relationship('Course', backref='student_list', secondary=temp_tab)

    __mapper_args__ = {  # 新的映射参数
        "order_by": age.desc()  # 降序
    }

    def __repr__(self):
        return "Student:name=%s, age=%s" % (self.name, self.age)

二、在relationship的方法中order_by属性

class Student(Base):
    __tablename__ = 't_student'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50))
    age = Column(Integer)
    
    course_list = relationship('Course', backref='student_list', secondary=temp_tab, order_by=age.desc())
    # course_list = relationship('Course', backref='student_list', secondary=temp_tab, order_by=age)

2、分页查询

  1. limit:可以限制查询的时候只查询前几条数据。
lst = session.query(Student).limit(10).all()
  1. offset:可以限制查找数据的时候过滤掉前面多少条。可指定开始查询时的偏移量。
lst = session.query(Student).offset(5).limit(10).all()
  1. 切片:可以对Query对象使用切片操作,来获取想要的数据。
lst = session.query(Student).slice(2, 8).all()  # 前开后闭
print(lst)
print(len(lst))  # 6
  • 可以使用 slice(start,stop) 方法来做切片操作。slice(step, stop),不包括step,包括stop。
  • 也可以使用 [start:stop] 的方式来进行切片操作。
  • 一般在实际开发中,中括号的形式是用得比较多的。

3、懒加载

在一对多,或者多对多关系的时候,如果想要获取多的一方这一部分的数据的时候,往往能通过一个属性就可以全部获取了。

但是有时候并不想获得所有的关联属性,那么这时候我们可以给relationship方法添加属性lazy='dynamic',以后通过.articles获取到的就不是一个列表,而是一个AppenderQuery对象了。

这样就可以对这个对象再进行一层过滤和排序等操作。

通过 lazy='dynamic' ,获取出来的多的那一部分的数据,就是一个 AppenderQuery 对象了。这种对象既可以添加新数据,也可以跟 Query 一样,可以再进行一层过滤。

from datetime import date
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref

engine = create_engine('mysql+pymysql://root:root@localhost:3306/flask_db?charset=utf8mb4', echo=True)

Base = declarative_base(engine)


# 部门和员工之间,是一种典型的一(主)对多(从)
class Dep(Base):
    __tablename__ = 't_dept'
    dept_no = Column(Integer, primary_key=True)
    d_name = Column(String(255))  # 部门名字
    city = Column(String(50))
    # 代表当前部门下所有员工的列表, 这种写法不是最优的, 最优的写法只要在其中一个对象中关联
    # emps = relationship("Emp")  # 参数必须是另外一个相关联的类名

    def __str__(self):
        return 'DEP:<部门名字:{}, 城市:{}>'.format(self.d_name, self.city)


# 员工表
class Emp(Base):
    __tablename__ = 't_emp'
    emp_no = Column(Integer, primary_key=True)
    emp_name = Column(String(50))  # 员工名字
    job = Column(String(50))
    hire_time = Column(DATE)  # 入职时间
    sal = Column(DECIMAL(10, 2))  # 薪资,连两位小数共十位
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='NO ACTION'))
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='CASCADE'))  # 级联删除
    dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='RESTRICT'))  #
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='SET NULL'))  #

    # 当前员工所属部门
    dept = relationship("Dep", backref=backref('emps', lazy='dynamic'), lazy='select')  # lazy默认值是select

    def __str__(self):
        return "EMP:<员工编号:{}, 员工姓名:{}>".format(self.emp_no, self.emp_name)


# Base.metadata.drop_all()
# Base.metadata.create_all()


# d1 = Dep(d_name='人事部', city='上海')
# d2 = Dep(d_name='销售部', city='上海')
# e1 = Emp(emp_name='张三', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=1)
# e2 = Emp(emp_name='李四', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=1)
# e3 = Emp(emp_name='王二', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=2)
# e4 = Emp(emp_name='麻子', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=2)

# 创建session对象
session = sessionmaker(engine)()


def test_lazy():
    d = session.query(Dep).filter(Dep.dept_no == 1)
    print(type(d))  # <class 'sqlalchemy.orm.query.Query'>
    print(d)  # 打印查询的SQL语句
    result = d.first()  # d.first 执行SQL语句  DEP:<部门名字:人事部, 城市:上海>
    print(result.emps)  # 当前对象是一个AppenderQuery对象:可以追加,排序,过滤
    e = Emp(emp_name='xxx', job='manager', hire_time=date(2022, 12, 27), sal=8888)
    result.emps.append(e)
    result.emps.filter(Emp.emp_no > 6).all()  # 过滤
    session.commit()


if __name__ == '__main__':
    test_lazy()

4. 分组过滤

group_by:根据某个字段进行分组。

统计每个工资级别下有多少员工。

result = session.query(Emp.sal, func.count(Emp.emp_no)).group_by(Emp.sal).all()

having:对分组查找结果作进一步过滤。

统计每个工资级别下有多少员工数量,只统计薪资大于3000以上的

# 统计每个工资级别下有多少员工数量,只统计薪资大于3000以上的
    result = session.query(Emp.sal, func.count(Emp.emp_no)).group_by(Emp.sal).having(Emp.sal > 3000).all()
    print(result)

5.子查询

5、子查询

子查询即select语句中还有select

那么在sqlalchemy中,要实现一个子查询,需以下几个步骤:

  1. 将子查询按照传统的方式写好查询代码,然后在 query 对象后面执行 subquery 方法,将这个查询变成一个子查询。

  2. 在子查询中,将以后需要用到的字段通过 label 方法,取个别名。

  3. 在父查询中,如果想要使用子查询的字段,那么可以通过子查询的返回值上的 c 属性拿到(c=Column)

查询和张三这个员工的职位、入职时间都相同的其他员工
在这里插入图片描述

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref

engine = create_engine('mysql+pymysql://root:root@localhost:3306/flask_db?charset=utf8mb4', echo=True)

Base = declarative_base(engine)


# 部门和员工之间,是一种典型的一(主)对多(从)
class Dep(Base):
    __tablename__ = 't_dept'
    dept_no = Column(Integer, primary_key=True)
    d_name = Column(String(255))  # 部门名字
    city = Column(String(50))
    # 代表当前部门下所有员工的列表, 这种写法不是最优的, 最优的写法只要在其中一个对象中关联
    # emps = relationship("Emp")  # 参数必须是另外一个相关联的类名

    def __str__(self):
        return 'DEP:<部门名字:{}, 城市:{}>'.format(self.d_name, self.city)


# 员工表
class Emp(Base):
    __tablename__ = 't_emp'
    emp_no = Column(Integer, primary_key=True)
    emp_name = Column(String(50))  # 员工名字
    job = Column(String(50))
    hire_time = Column(DATE)  # 入职时间
    sal = Column(DECIMAL(10, 2))  # 薪资,连两位小数共十位
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='NO ACTION'))
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='CASCADE'))  # 级联删除
    dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='RESTRICT'))  #
    # dept_no = Column(Integer, ForeignKey('t_dept.dept_no', ondelete='SET NULL'))  #

    # 当前员工所属部门
    dept = relationship("Dep", backref=backref('emps', lazy='dynamic'), lazy='select')  # lazy默认值是select

    def __repr__(self):
        return "EMP:<员工编号:{}, 员工姓名:{}>".format(self.emp_no, self.emp_name)


# Base.metadata.drop_all()
# Base.metadata.create_all()


# d1 = Dep(d_name='人事部', city='上海')
# d2 = Dep(d_name='销售部', city='上海')
# e1 = Emp(emp_name='张三', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=1)
# e2 = Emp(emp_name='李四', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=1)
# e3 = Emp(emp_name='王二', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=2)
# e4 = Emp(emp_name='麻子', job='经理', hire_time=date(2022, 12, 22), sal=6666.50, dept_no=2)

# 创建session对象
session = sessionmaker(engine)()


def test_group():
    # 统计每个工资级别下有多少员工数量
    result = session.query(Emp.sal, func.count(Emp.emp_no)).group_by(Emp.sal).all()
    print(result)

    # 统计每个工资级别下有多少员工数量,只统计薪资大于3000以上的
    result = session.query(Emp.sal, func.count(Emp.emp_no)).group_by(Emp.sal).having(Emp.sal > 3000).all()
    print(result)


def test_subQuery():
    # 查询和张三这个员工的职位、入职时间都相同的其他员工
    # 1.写子查询
    stmt = session.query(Emp.hire_time.label('ht'), Emp.job.label('jb')).filter(Emp.emp_name == '张三').subquery()
    # 2.写父查询
    result = session.query(Emp).filter(Emp.hire_time == stmt.c.ht, Emp.job == stmt.c.jb).all()
    print(result)


if __name__ == '__main__':
    # test_group()
    test_subQuery()

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WinNTSetup V5.3.0 Bata5 单文件版

前言 WinNTSetup 是一款Windows系统硬盘安装器&#xff0c;支持从PE和本地安装系统&#xff0c;支持支持NT内核的系统。 WinNTSetup 包括XP、Win7、Win8、Win8.1、Win10等这些系统。直接从硬盘安装系统&#xff0c;不需要光盘。WinNTSetup 还附加一些系统优化功能&#xff0…

Android---简易的底部导航栏

目录 一、activity_main.xml布局 二、给ViewPager2 创建适配器 三、ViewPager2 数据源 四、MainActivity.java类 1、初始化数据源。 2、ViewPager2 页面改变监听 3、BottomNavigationView 的每个 item 点击的监听 这里简单演示实现效果&#xff0c;实现快速开发&#xff…

mmdetection从入门到精通(一)-汇总目录

&#xff11;.简介 MMDetection 是商汤出品的集成了目标检测&#xff0f;实例分割分割&#xff0f;全景分割几个方面顶级模型组合的,模块化的&#xff0c;基于 PyTorch 的目标检测开源工具箱。是深度学习工作者的必备工具&#xff0c;非常有必要深入掌握。 近期汇总一下从入…

今年最后一场官方活动

阅读本文大概需要 1.6 分钟。2022 年 12 月 26&#xff0c;新型冠状病毒肺炎正式更名为了新型冠状病毒感染&#xff0c;不再纳入《中华人民共和国国境卫生检查疫法》 规定的检疫传染病管理。文字层面上&#xff0c;这意味着我们口中的疫情&#xff0c;结束了。然而我却认为并没…

Django学习 Day9

1.F对象 一个F对象代表数据库中某条记录的字段的信息。 作用&#xff1a; 通常是对数据库中的字段的值在不获取的情况下进行操作 用于类属性&#xff08;字段&#xff09;之间的比较。 语法&#xff1a; From django.db.models import F F(‘列名’)例子: 所有Book数据表中的…

云游戏的2022:破局、新生、元宇宙

文|智能相对论 作者|青月 如果说2021年是「元宇宙元年」&#xff0c;那么2022年更像是元宇宙的「祛魅之年」&#xff0c;在这一年里&#xff0c;原本处在狂奔状态下的元宇宙正在褪去虚火。 在这样的大环境下&#xff0c;由于在实时性、兼容性、无限开创等关键特性的理念上的…

99. 激光炸弹——二维前缀和

地图上有 N 个目标&#xff0c;用整数 Xi,Yi 表示目标在地图上的位置&#xff0c;每个目标都有一个价值 Wi。 注意&#xff1a;不同目标可能在同一位置。 现在有一种新型的激光炸弹&#xff0c;可以摧毁一个包含 RR 个位置的正方形内的所有目标。 激光炸弹的投放是通过卫星定…

eclipse中安装ERMaster

eclipse中安装ERMaster 简介 参考网址&#xff1a; https://www.bilibili.com/video/BV1R4411a73T/?p22&spm_id_from333.880.my_history.page.click&vd_source42661b67a37800001020550eb4a4c45e 主要看这 3 集 ERMaster 在 jeesite 官网的介绍项目 参考网址&#x…

systemd(二)单元配置文件

概述 对于系统中的每一个单元&#xff08;unit&#xff09;都有一个配置文件&#xff0c;用于指示systemd如何启动或停止这个单元。 配置文件格式 [Unit]区块 [Unit]区块通常是配置文件的第一个区块&#xff0c;用来定义单元的元数据&#xff0c;以及配置与其他单元的关系。…

多线程模式下保证事物的一致性

目录前置InsertBatchSuccessServiceImpl.javaInsertBatchErrorServiceImpl.java效果图前置 在一些特殊的场景下, 我们需要一些特定的操作. 比如我有一个接口, 做如下操作, 需要保持事物的一致性, 即: 全部成功则提交, 一个异常则全部回滚: 1.insert订单、(耗时1秒) 2.insert订单…

4、MYSQL常用函数(字符串函数)

目录 1、concat函数&#xff1a; 2、insert(str,x,y,instr)函数&#xff1a; 3、lower(str)和upper(str)函数&#xff1a; 4、left(str,x)和right(str,x)函数&#xff1a; 5、lpad(str,n,pad) 和rpad(str,n,pad) 函数&#xff1a; 6、ltrim(str)和rtrim(str)函数&#xff…

【大厂高频真题100题】《除自身以外数组的乘积》 真题练习第19题 持续更新~

除自身以外数组的乘积 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法,且在 O(n) 时间复杂度内完成…

微软补丁包下载

Microsoft Update Cataloghttps://www.catalog.update.microsoft.com/Home.aspxMicrosoft Update CatalogMicrosoft Update Cataloghttps://www.catalog.update.microsoft.com/Home.aspx

城市通信管线资源管理解决方案

01 背景 随着新基建发展&#xff0c;智慧项目如火如荼&#xff0c;网络畅通、高速成为了刚需&#xff0c;城市通信网络管线资源重要性不言而喻&#xff0c;在实际项目中&#xff0c;我们也不难发现有关于“通信网络管线管理”“光缆资源管理”项目愈发增多&#xff0c;大多客户…

(五)JSP

一、JSP 概述 JSP&#xff08;全称&#xff1a;Java Server Pages&#xff09;&#xff1a;Java 服务端页面。是一种动态的网页技术&#xff0c;其中既可以定义HTML、JS、CSS等静态内容&#xff0c;还可以定义Java代码的动态内容&#xff0c;也就是 JSP HTML Java 。二、JSP …

基于注解的AOP之准备工作以及各种通知

目录 基于注解的AOP之准备工作以及各种通知 1. 技术说明 2. 准备工作 ①添加依赖 ②准备被代理的目标资源 3. 创建切面类并配置 在Spring的配置文件中配置&#xff1a; ​​​​​​4. 各种通知 各种通知的执行顺序&#xff1a; 基于注解的AOP之准备工作以及各种通知 …

C++【B树】【B+树】

文章目录一、什么是B树1.为什么要存在B树&#xff1f;2.B树的规则二、B树的插入三、B树的实现时间复杂度四、B树1.B树的分类过程五、B*树六、B树系列的应用1.MyISAM2.InnoDB一、什么是B树 相比于我们别的数据结构&#xff0c;我们的B树更加适合进行外查找 B树也可以进行内查找…

元启发式算法-模拟退火算法MATLAB实现

元启发式算法-模拟退火算法MATLAB实现 模拟退火介绍 模拟退火算法来源于固体退火原理&#xff0c;是一种基于概率的算法&#xff0c;将固体加温至充分高&#xff0c;再让其徐徐冷却&#xff0c;加温时&#xff0c;固体内部粒子随温升变为无序状&#xff0c;内能增大&#xff0…

SpringBoot系列教程之定义接口返回类型的几种方式

本文节选自 《Spring WEB专栏》 WEB系列】 定义接口返回类型的几种方式 实现一个 web 接口返回 json 数据&#xff0c;基本上是每一个 javaer 非常熟悉的事情了&#xff1b;那么问题来了&#xff0c;如果我有一个接口&#xff0c;除了希望返回 json 格式的数据之外&#xff0c…

Linux内核学习笔记——内核页表隔离KPTI机制

接前文。 一步一步理解CPU芯片漏洞&#xff1a;Meltdown与Spectre ARM系列之MMU TLB和ASID基础概念介绍。 一、Meltdown & Spectre 漏洞 Meltdown 和 Spectre 这两个漏洞厉害的地方就在于&#xff0c;利用现代CPU speculative execution (预测执行)的漏洞&#xff0c;在…