Python ORM编程基础:原理、CRUD与Peewee实战
本文深入解析Python ORM(对象关系映射)的核心原理,涵盖数据类型、类及关系的映射机制。详细阐述ORM如何自动处理增删改查(CRUD)及缓存优化,并通过Peewee库展示从建表、外键关联到复杂查询的完整实战代码,帮助开发者高效进行数据库编程。
本文通过具体实例介绍Python中的ORM编程技术,旨在为读者提供可参考的学习资料。
ORM编程概述
ORM编程概述
ORM(Object-Relational Mapping,对象关系映射)的主要作用是在关系型数据库与业务实体对象之间建立映射关系。其核心价值在于简化开发流程,使开发者无需编写复杂的SQL语句,仅需通过操作对象的属性和方法即可完成数据交互。所有ORM框架均具备三项基本能力:映射技术、CRUD(增删改查)操作以及缓存优化。不同编程语言拥有各自的ORM库,例如Java的Hibernate和IBATIS、C#的Grove LINQ,以及Python的SQLAlchemy等。
映射技术原理
1、映射技术
面向对象编程源于软件工程的基本原则,如耦合、聚合和封装;而关系型数据库则建立在数学理论的基础之上。ORM旨在弥合这两种范式之间的差异。
ORM库需要解决以下三个核心问题:
- 数据类型映射:将数据库中的字段类型转换为编程语言中对应的数据类型。
- 类映射:将数据库中的表结构定义映射为编程语言中的类定义。
- 关系映射:将数据库中基于外键的连接关系,转换为编程语言中基于对象引用的关联关系。
CRUD操作流程
2、CRUD操作
- C – Create(创建/增加)
- R – Retrieve(读取,即从数据库重新获取数据)
- U – Update(更新)
- D – Delete(删除)
在原生SQL中,通常使用insert、select、update和delete四种语句来实现CRUD功能。
ORM框架会自动实现以下操作流程:
- 将高级语言的调用转换为标准的SQL语句。
- 通过数据库引擎将SQL语句发送给数据库执行。
- 将数据库返回的结果集,利用映射技术转换回编程语言中的类对象。
缓存优化机制
3、缓存优化
- 将从数据库查询到的数据以类对象的形式保存在本地内存中,以便后续使用时可以直接抽取,无需再次访问数据库。
- 真正的数据库select操作仅在真正需要读取查询结果时执行,而不是在ORM查询命令发出时立即查询数据库,从而提升性能。
Peewee实战示例
4、使用Peewee进行ORM数据库编程
实现思路如下:
- 导入必要的包(如peewee),并建立一个数据库引擎对象db。
- 定义一个ORM基类BaseModel(),建立与SQLite数据库的连接。
- 进行类型映射:定义所需的数据类型字段。
- 进行表映射:定义两个对象类,分别为course和teacher。
- 进行关系映射:使用ForeignKeyField设置与course的连接关系。其中,to_field参数用于指定被连接的字段名,related_name参数为该关系赋予一个名称。
import os
if os.path.exists('sampleDB.db'):
os.remove('sampleDB.db')
# 引入peewee包的所有内容
from peewee import *
# 建立一个Sqlite数据库引擎对象,该引擎打开数据库文件sampleDB.db
db = SqliteDatabase("sampleDB.db")
# 定义一个ORM的基类,在基类中指定本ORM所使用的数据库,
# 这样在之后所有的子类中就不用重复声明数据库
class BaseModel(Model):
class Meta:
database = db
# 定义course表,继承自BaseModel
class Course(BaseModel):
id = PrimaryKeyField() # 定义主键
title = CharField(null=False) # 定义字符串
period = IntegerField() # 整型
description = CharField()
class Meta:
order_by = ('title',)
db_table = 'course' # 定义数据库中的表名
# 定义 teacher 表,继承自BaseModel
class Teacher(BaseModel):
id = PrimaryKeyField()
name = CharField(null=False)
gender = BooleanField() # 布尔型
address = CharField()
# ForeignKeyField 设置与course的连接关系,其中的参数:to_field用于指定被连接的字段名,related_name参数对该关系赋予了一个名字
course_id = ForeignKeyField(Course, to_field="id", related_name="course")
class Meta:
order_by = ('name',)
db_table = "teacher"
# 建表,仅需创建一次
Course.create_table()
Teacher.create_table()
# 新增行
Course.create(id=1, title='经济学', period=320, description='文理科学生均可选修')
Course.create(id=2, title='大学英语', period=300, description='大一学生必修课')
Course.create(id=3, title='哲学', period=100, description='必修课')
Course.create(id=134, title='编译原理', period=100, description='计算机系选修')
Teacher.create(name='白阵君', gender=True, address='..', course_id=1)
Teacher.create(name='李森', gender=True, address='..', course_id=3)
Teacher.create(name='张雯雯', gender=False, address='..', course_id=2)
# 查询一行
record = Course.get(Course.title == '大学英语')
print("课程:%s, 学时:%d, 课程类型: %s" % (record.title, record.period, record.description))
# 更新
record.period = 200
record.save()
# 删除
record.delete_instance()
# 查询所有记录
courses = Course.select()
for i in courses:
print(i.id, i.title, i.period, i.description)
# 带条件查询,并将结果按period字段倒序排序
courses = Course.select().where(Course.id< 10).order_by(Course.period.desc())
for i in courses:
print(i.id, i.title, i.period, i.description)
# 统计所有课程的平均学时
total = Course.select(fn.Avg (Course.period).alias('avg_period'))
for i in total:
print(u"平均学时:", i.avg_period)
# 更新多个记录
Course.update(period=300).where(Course.id > 100).execute()
# 多表连接操作,Peewee会自动根据ForeignKeyField的外键定义进行连接:
Record = Course.select().join(Teacher).where(Teacher.gender == True)
for i in Record:
print(i.id, i.title, i.period, i.description)
参考来源:书籍《python 高效开发实战》。
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python常见数据库操作技巧汇总》、《Python数学运算技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》。
希望本文所述内容对大家学习Python程序设计有所帮助。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













