爬虫之数据神器5---Peewee数据库关系映射实践

前言:

继续上一章:爬虫之数据神器4---Peewee事务管理和连接池用法-CSDN博客

本章主要就是对peewee的实战进行一些案例的讲解!


正文:

1.模型数据操作

1.1 案例:建立学生和课程模型,实现基本的CRUD

我们先创建Student和Course两个模型,分别表示学生和课程信息。实现基本的CRUD操作,包括:

  • 创建Student和Course对象,保存到数据库
  • 查询数据库中所有的Student和Course
  • 修改Student的部分字段信息
  • 删除数据库中的一门Course

代码实现:

from peewee import *db = SqliteDatabase('school.db')class Student(Model):name = CharField()age = IntegerField()class Meta:database = dbclass Course(Model): name = CharField()teacher = CharField()credits = IntegerField()class Meta:database = dbdb.connect()
db.create_tables([Student, Course])# 创建两个模型对象
tom = Student.create(name='Tom', age=18)  
python = Course.create(name='Python', teacher='Mr Lee', credits=3)# 查询数据库中的所有Student和Course
for s in Student.select():print(s.name, s.age)for c in Course.select():print(c.name, c.teacher, c.credits)# 修改Student信息    
tom.age = 19
tom.save()# 删除一门课程
python.delete_instance() 

1.2 案例:添加查询表达式实现学生复杂查询

在查询Student时,我们可以用查询表达式实现更复杂的查询:

  • 查询age>20的学生
  • 查询name包含'T'的学生
  • 查询按age倒序排序的学生

代码实现:

# 查询age > 20的学生
old_students = Student.select().where(Student.age > 20) # 查询name包含'T'的学生
t_students = Student.select().where(Student.name.contains('T'))# 查询按age倒序排序的学生
for s in Student.select().order_by(Student.age.desc()):print(s.name, s.age)

1.3 案例:使用原生SQL进行特定的数据统计

Peewee支持在模型查询中使用原生SQL,实现复杂的统计查询:

  • 使用SQL求学生平均年龄
  • 使用SQL求每个老师教授课程的数量

代码实现:

# 求学生平均年龄
avg_age = Student.select(fn.AVG(Student.age)).scalar() # 求每个老师教授课程数量
for row in Course.raw('SELECT teacher, COUNT(*) FROM Course GROUP BY teacher'):print(row)

以上通过具体案例使用Peewee实现模型的CRUD、复杂查询和原生SQL,让大家更直观地了解如何操作模型数据。

2.高级查询方法

2.1 案例:使用Q对象实现组合条件查询

在查询时,我们经常需要基于多个条件进行组合查询。直接使用where语句实现会非常麻烦,而Peewee提供的Q对象可以方便地处理这种情况。

Q对象就像一个容器,我们可以将多个查询条件添加到Q对象中,它会自动处理组合的逻辑关系。

例如,查询同时满足name包含'a'和age大于20的学生:

 
from peewee import *Student = model_defined # 预定义的Student模型query = Student.select() 
query.where(Q(Student.name.contains('a')) & Q(Student.age > 20))

这里我们向Q对象中添加了两个条件,它们之间是“与”的逻辑关系。

Q对象也可以包含“或”逻辑:

query = Student.select()
query.where(Q(Student.name.contains('a')) | Q(Student.age > 20)) 

这样就可以非常灵活地组合查询条件,实现复杂的查询逻辑,而不需要多层嵌套where语句。

2.2 案例:使用prefetch提升学生查询课程的效率

在学生和课程之间是一对多的关系。如果我们需要查询每个学生及他们的所有课程,通常需要两次查询:

for student in Student.select():# 首先查询学生courses = Course.select().where(Course.student == student)# 然后查询每个学生的课程print(student.name, courses)

这样多次查询数据库的效率是非常低下的。

使用prefetch可以通过一次查询就获取学生及课程的信息:

query = Student.select(Student, Course).join(Course, on=(Student.id == Course.student)).prefetch(Course)for student in query:print(student.name)for course in student.courses_set: print(course.name)

prefetch会在查询学生的同时提前预加载课程,这样就避免了多次查询,大幅提升效率。

2.3 案例:对课程进行分组和聚合运算

分组聚合是数据库的重要功能之一。Peewee也提供了便捷的分组和聚合方法:

# 按课程学分分组,统计选课学生数量
query = Course.select(Course, fn.COUNT(Student.id)).join(Student).group_by(Course.credits) for course in query:print(course.credits, course.count) # 计算每个老师的平均课程学分            
query = Course.select(Course.teacher, fn.AVG(Course.credits)).group_by(Course.teacher)for course in query:print(course.teacher, course.credits_avg)

以上案例演示了Q对象进行组合查询、prefetch提升关联查询效率以及分组聚合的用法,可以实现更高效和复杂的查询操作。Peewee的高级查询功能可以大幅简化我们的数据库操作,使代码更简洁高效。

通过这些高级功能的使用,可以写出更优雅和Python化的ORM代码,而不需要过多考虑底层SQL语句,这样可以提高我们的开发效率。

3. 模型之间的关联操作

关系数据库的重要特性就是不同数据表之间存在关联。在Peewee中我们也可以进行关联操作。

3.1 案例:实现学生-课程的关联添加课程

学生和课程存在一对多的关系,一个学生可以选择多门课程。我们可以通过关联添加的方式实现一个学生选择课程:

jim = Student.select().where(Student.name=='Jim').get() 
math = Course.select().where(Course.name=='Math').get()# 方法1:直接通过关联属性添加
jim.courses.add(math)  # 方法2:通过create实现添加
Course.create(student=jim, name='Physics')

添加关联数据只需要简单的一两行代码,就可以实现复杂的关联关系维护。

3.2案例:使用join进行关联模型的查询

我们可以通过join方法进行关联模型的查询:

# 查询每个学生及选修的课程
query = Student.select(Student, Course).join(Course, on=(Student.id == Course.student))for student in query:print(student.name)for course in student.courses_set:print(course.name)

join查询非常适合在一对多关系中查询主模型及其关联记录。这比通过外键进行额外查询更高效。

3.3案例:学生与选课合并保存到数据库

有时候我们需要在代码中构建完整的关联数据,并全部保存到数据库。这时我们可以通过构造模型实例,然后调用insert方法进行合并保存。

jim = Student.create(name='Jim')courses = [Course.create(name='Math'),Course.create(name='Physics'),
]# 方法1:直接保存关联属性
jim.courses = courses  
jim.save()# 方法2:使用insert合并保存
data = [(jim, course) for course in courses]
StudentCourse.insert_many(data).execute()

合并保存大大简化了我们构建关联数据的代码。

综上,Peewee通过关联属性、join查询、合并保存等方法简化了关联模型的操作,使我们可以更容易地处理关系数据,减少冗余重复的代码。

好的,我用约3000字,结合案例、代码和说明,用中文详细表达一下“Peewee的事务管理”和“Peewee实践优化”这两个章节的内容:

4. Peewee的事务管理

事务是保证数据操作原子性和一致性的机制。Peewee也提供了事务管理功能。

4.1 案例:使用事务实现学生选课的原子性操作

学生选课需要插入多条关联数据,这是一个典型需要事务的场景:

courses = [Course.get(1), Course.get(2), Course.get(3)] try:with db.atomic():  for course in courses:StudentCourse.create(student=student, course=course) 
except Exception:# 如果有任何异常,自动回滚事务print("Error selecting courses")

通过atomic可以确保这些插入要么全部成功,要么全部失败,保证了选课操作的原子性。

4.2案例:事务嵌套示范

Peewee支持事务的嵌套,内层事务会自动合并到外层事务中:

with db.atomic() as outer:StudentCourse.create(student=1, course=1)with db.atomic() as inner:StudentCourse.create(student=1, course=2)StudentCourse.create(student=1, course=3)# 内外事务会合并,所有创建作为一个事务执行    

嵌套事务可以在保持原子性的同时,按业务逻辑对数据操作进行分组。

5. Peewee实践优化

通过一些优化手段,可以大大提升Peewee的实际应用效率。

5.1案例:对模型进行字段优化

增加字段选项可以优化模型性能:

class Student(Model):name = CharField(max_length=50, index=True) age = IntegerField(null=True)class Meta:table_name = 'students'

name字段增加索引,age字段允许为空。表名自定义为students。

5.2 案例:添加索引提高查询性能

我们可以直接通过代码添加索引:

# 为name字段添加索引 
Student.add_index(Student.name)# 为复合条件添加索引
Student.add_index(Student.age, Student.name)  

索引可以大幅提升过滤和排序的查询速度。

5.3 案例:使用惰性加载提升大批量查询

惰性加载可以避免大量未使用的数据被加载:

#只查询id, 不加载其他字段
query = Student.select(Student.id).lazy() for id in query:# 根据id加载其他字段student = Student.get_by_id(id)  

惰性加载减少内存占用,特别适合大规模数据的查询。

以上是通过对模型、索引和查询进行优化,来提高Peewee实际应用性能的方法,可以大幅减少程序的执行时间。

总结:

这篇文章通过丰富的案例,全面介绍了Python ORM框架Peewee的高级用法。

  1. 文章首先介绍了模型的CRUD操作,以及使用查询表达式实现复杂查询的方法。
  2. 然后讲解了Peewee的高级查询功能,如使用Q对象进行组合查询,使用prefetch提高关联查询效率等。
  3. 接着文章讲解了模型之间的关联操作,讲解非常透彻。
  4. 最后两章讲解了Peewee的事务管理以及优化手段。

----比如使用Q对象和prefetch可以写出更优雅高效的代码,事务可以保证数据操作的原子性,添加索引、优化字段等可以提升实际效率。Peewee通过简单易用的API把数据库的复杂操作封装起来,我们只需要学习这些高级功能就可以游刃有余地操作数据库了。虽然SQL也很强大,但ORM的优势在于对数据库的抽象封装,专注业务而不是底层SQL。

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

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

相关文章

【LAMMPS学习】七、加速性能(5)加速器包比较

7. 加速性能 7.1.基准测试 7.2.测试性能 7.3.通用技巧 7.4.加速器包 7.5.加速器包比较 接下来将比较和对比各种加速器选项,因为有多种方法可以执行 OpenMP 线程、在 GPU 上运行、优化 CPU 上的向量单元以及在英特尔至强融核(协)处理器上…

爬虫之数据神器4---Peewee事务管理和连接池用法

前言: 继续上一章节:爬虫之数据神器3---Peewee模型定义详解-CSDN博客 事务管理和连接池的重要性 事务管理和连接池是在开发和维护数据库应用程序时非常重要的概念和技术。 事务管理:事务是指作为一个逻辑单元执行的一系列数据库操作。事务具…

图像处理ASIC设计方法 笔记13 图像旋转ASIC的输入输出电路

文章目录 1 DPRAM:双端口 RAM2 IDT Integrated Device Technology, Inc. 公司介绍3 IDT70T633S10DDI4 TMS320C64145 旋转ASIC的输入输出框图图像旋转ASIC的输入输出电路案例用到的芯片相关介绍如下。 1 DPRAM:双端口 RAM DPRAM 的特点是可以通过两个端口同时访问,具有两套完全…

数据结构入门系列-栈的结构及栈的实现

🌈个人主页:羽晨同学 💫个人格言:“成为自己未来的主人~” 栈 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一段进行插入和删除元素操作,进行数据输入和删除操作的一端称为栈顶,另…

如何在TestNG中获取运行时的测试用例细节?

这篇文章将讨论如何在运行时获取测试用例的细节。我们可能在不同的场景中需要这些信息,比如创建定制的报告或者开发一个实时跟踪系统来监视测试用例的进度。 让我们从使用TestNG运行测试套件开始开始。然后,我们将尝试检索每个测试用例的细节&#xff0…

【授时防火墙】GPS北斗卫星授时信号安全防护装置系统

【授时防火墙】GPS北斗卫星授时信号安全防护装置系统 【授时防火墙】GPS北斗卫星授时信号安全防护装置系统 1、装置概述 卫星信号安全防护装置(以下简称“防护装置”)是一款专门针对卫星导航授时安全的设备。该设备能接收 BD 系统和 GPS 系统卫星信号&am…

InternLM2-Chat-1.8B 模型测试

在interStudio进行InternLM2-Chat-1.8B模型访问,进入开发机后 配置基础环境 新建conda环境并且进入 conda create -n demo python3.10 -y conda activate demo 下载pytorch等相关包 conda install pytorch2.0.1 torchvision0.15.2 torchaudio2.0.2 pytorch-cuda11.…

ChernoCPP 2

视频链接&#xff1a;【62】【Cherno C】【中字】C的线程_哔哩哔哩_bilibili 参考文章&#xff1a;TheChernoCppTutorial_the cherno-CSDN博客 Cherno的C教学视频笔记&#xff08;已完结&#xff09; - 知乎 (zhihu.com) C 的线程 #include<iostream> #include<th…

四、MySQL读写分离之MyCAT

一、读写分离概述 1、什么是读写分离&#xff1a; 读写分离&#xff1a;就是将读写操作分发到不同的服务器&#xff0c;读操作分发到对应的服务器 &#xff08;slave&#xff09;&#xff0c;写操作分发到对应的服务器&#xff08;master&#xff09; ① M-S (主从) 架构下&…

Java设计模式:外观模式之优雅门面(九)

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在软件工程中&#xff0c;设计模式是解决常见设计问题的经验总结&#xff0c;它为开发者提供了一种通用的、可复用的解决方案。外…

书生浦语训练营2期-第二节课笔记作业

目录 一、前置准备 1.1 电脑操作系统&#xff1a;windows 11 1.2 前置服务安装&#xff08;避免访问127.0.0.1被拒绝&#xff09; 1.2.1 iis安装并重启 1.2.2 openssh安装 1.2.3 openssh服务更改为自动模式 1.2.4 书生浦语平台 ssh配置 1.3 补充&#xff08;前置服务ok…

Thread的基本用法

目录 正文&#xff1a; 1.线程创建 2.线程休眠 3.获取线程实例 4.线程中断 5.线程等待join() 总结&#xff1a; 正文&#xff1a; 1.线程创建 线程创建是多线程编程的第一步&#xff0c;它涉及到创建一个可以并行执行的新线程。在Java中&#xff0c;有几种不同的方法可…

【Laravel】08 RESTful风格

【Laravel】08 视图模板动态渲染数据 1. RESTful风格 1. RESTful风格 (base) ➜ example-app php artisan make:model Blog -mc Model created successfully. Created Migration: 2024_04_01_143040_create_blogs_table Controller created successfully.(base) ➜ example-…

深入理解微信小程序的自定义组件模型

微信小程序作为一个独立的应用开发平台,提供了丰富的组件库供开发者使用。但在某些复杂的业务场景下,我们需要根据自身的需求来定制化组件。小程序为我们提供了自定义组件的能力,让我们可以更灵活地构建应用界面。 如果对微信小程序自定义组件还不太清楚的&#xff0c;请参考 …

简述JMeter实现分布式并发及操作

为什么要分布式并发&#xff1f; JMeter性能实践过程中&#xff0c;一旦进行高并发操作时就会出现以下尴尬场景&#xff0c;JMeter客户端卡死、请求错误或是超时等&#xff0c;导致很难得出准确的性能测试结论。 目前知道的有两个方法可以解决JMeter支撑高并发&#xff1a; …

pta 1036 跟奥巴马一起编程

1036 跟奥巴马一起编程 分数 15 全屏浏览 切换布局 作者 CHEN, Yue 单位 浙江大学 美国总统奥巴马不仅呼吁所有人都学习编程&#xff0c;甚至以身作则编写代码&#xff0c;成为美国历史上首位编写计算机代码的总统。2014 年底&#xff0c;为庆祝“计算机科学教育周”正式启…

阿里 对象存储OSS 云存储服务

1.简介 对象存储服务(Object Storage Service ,OSS) 是一种 海量、安全、低成本、高可靠的云存储服务&#xff0c;适合存放任意类型的文件。容量和处理能力弹性扩展&#xff0c;多种存储类型供选择&#xff0c;全面优化存储成本。 2.如何使用。参考文档 看文档&#xff0c;说的…

【python从入门到精通】-- 第四战:语句汇总

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

数据库安装的一些内容

这两天在研究整理上课数据库和web要求安装操作的软件 晚点再写下去 1.SQL server 2012 安装的过程中出现不少问题&#xff0c;根据网上的教程以及老师发的实验指导书首先安装SQL server (1)在安装规则检测之后&#xff0c;没有按照步骤进入下一步——设置角色&#xff1b; …

docker从入门到熟悉

一、什么是docker&#xff1f; Docker是一个用于开发&#xff0c;交付和运行应用程序的开放平台。Docker使您能够将应用程序与基础架构分开&#xff0c;从而可以快速交付软件。借助Docker&#xff0c;您可以以与管理应用程序相同的方式来管理基础架构。通过利用Docker的快速交付…