当前位置: 首页 > news >正文

Python ORM 完全指南:从基础到高级实践

1. ORM 基础概念

ORM(Object-Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言中实现与关系型数据库的交互。ORM 将数据库表映射为编程语言中的类,将表中的行映射为对象实例,将表中的列映射为对象属性。

为什么使用 ORM?

  • 提高开发效率:减少编写重复的 SQL 语句

  • 数据库无关性:可以轻松切换数据库后端

  • 安全性:自动防止 SQL 注入攻击

  • 面向对象:使用熟悉的面向对象范式操作数据库

2. Python 主流 ORM 框架

2.1 SQLAlchemy

SQLAlchemy 是 Python 社区最流行的 ORM 框架之一,提供了完整的 ORM 功能。

python

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmakerBase = declarative_base()class User(Base):__tablename__ = 'users'id = Column(Integer, primary_key=True)name = Column(String)age = Column(Integer)# 创建引擎
engine = create_engine('sqlite:///example.db')
Base.metadata.create_all(engine)# 创建会话
Session = sessionmaker(bind=engine)
session = Session()# 添加新用户
new_user = User(name='Alice', age=25)
session.add(new_user)
session.commit()# 查询用户
users = session.query(User).filter(User.age > 20).all()
for user in users:print(user.name, user.age)

2.2 Django ORM

Django 内置的 ORM 是 Django 框架的一部分,简单易用。

python

from django.db import modelsclass User(models.Model):name = models.CharField(max_length=100)age = models.IntegerField()def __str__(self):return self.name# 创建记录
User.objects.create(name='Bob', age=30)# 查询记录
users = User.objects.filter(age__gt=25)
for user in users:print(user.name, user.age)

2.3 Peewee

Peewee 是一个轻量级的 Python ORM,适合小型项目。

python

from peewee import *db = SqliteDatabase('example.db')class User(Model):name = CharField()age = IntegerField()class Meta:database = dbdb.connect()
db.create_tables([User])# 创建记录
User.create(name='Charlie', age=35)# 查询记录
users = User.select().where(User.age > 25)
for user in users:print(user.name, user.age)

3. ORM 核心功能

3.1 模型定义

python

# SQLAlchemy 示例
class Product(Base):__tablename__ = 'products'id = Column(Integer, primary_key=True)name = Column(String(100), nullable=False)price = Column(Float)category = Column(String(50))# 定义关系reviews = relationship("Review", back_populates="product")class Review(Base):__tablename__ = 'reviews'id = Column(Integer, primary_key=True)content = Column(Text)rating = Column(Integer)product_id = Column(Integer, ForeignKey('products.id'))product = relationship("Product", back_populates="reviews")

3.2 CRUD 操作

python

# 创建 (Create)
new_product = Product(name='Laptop', price=999.99, category='Electronics')
session.add(new_product)
session.commit()# 读取 (Read)
# 获取单个对象
product = session.query(Product).get(1)# 获取多个对象
cheap_products = session.query(Product).filter(Product.price < 500).all()# 更新 (Update)
product = session.query(Product).get(1)
product.price = 899.99
session.commit()# 删除 (Delete)
product = session.query(Product).get(1)
session.delete(product)
session.commit()

3.3 高级查询

python

# 复杂查询
from sqlalchemy import and_, or_# AND 条件
results = session.query(Product).filter(and_(Product.price < 500,Product.category == 'Electronics')
).all()# OR 条件
results = session.query(Product).filter(or_(Product.category == 'Electronics',Product.category == 'Books')
).all()# 排序
results = session.query(Product).order_by(Product.price.desc()).all()# 分页
page_size = 10
page_number = 2
results = session.query(Product).limit(page_size).offset((page_number-1)*page_size).all()# 聚合函数
from sqlalchemy import funcavg_price = session.query(func.avg(Product.price)).scalar()
max_price = session.query(func.max(Product.price)).scalar()

4. 关系与关联

4.1 一对多关系

python

# SQLAlchemy 示例
class Author(Base):__tablename__ = 'authors'id = Column(Integer, primary_key=True)name = Column(String)books = relationship("Book", back_populates="author")class Book(Base):__tablename__ = 'books'id = Column(Integer, primary_key=True)title = Column(String)author_id = Column(Integer, ForeignKey('authors.id'))author = relationship("Author", back_populates="books")# 使用示例
author = Author(name='J.K. Rowling')
book1 = Book(title='Harry Potter 1', author=author)
book2 = Book(title='Harry Potter 2', author=author)session.add_all([author, book1, book2])
session.commit()# 查询作者的所有书籍
author = session.query(Author).first()
for book in author.books:print(book.title)

4.2 多对多关系

python

# 需要中间关联表
book_tags = Table('book_tags', Base.metadata,Column('book_id', Integer, ForeignKey('books.id')),Column('tag_id', Integer, ForeignKey('tags.id'))
)class Tag(Base):__tablename__ = 'tags'id = Column(Integer, primary_key=True)name = Column(String)books = relationship("Book", secondary=book_tags, back_populates="tags")class Book(Base):__tablename__ = 'books'id = Column(Integer, primary_key=True)title = Column(String)tags = relationship("Tag", secondary=book_tags, back_populates="books")# 使用示例
book = Book(title='Python Cookbook')
tag1 = Tag(name='Programming')
tag2 = Tag(name='Python')book.tags.extend([tag1, tag2])
session.add(book)
session.commit()# 查询书籍的所有标签
book = session.query(Book).first()
for tag in book.tags:print(tag.name)

5. ORM 高级特性

5.1 混合属性 (Hybrid Attributes)

python

from sqlalchemy.ext.hybrid import hybrid_propertyclass Product(Base):# ... 其他字段 ...price = Column(Float)tax_rate = Column(Float)@hybrid_propertydef price_with_tax(self):return self.price * (1 + self.tax_rate)@price_with_tax.expressiondef price_with_tax(cls):return cls.price * (1 + cls.tax_rate)# 可以在查询中使用
expensive_products = session.query(Product).filter(Product.price_with_tax > 1000
).all()

5.2 事件监听

python

from sqlalchemy import event@event.listens_for(Product.price, 'set')
def validate_price(target, value, oldvalue, initiator):if value < 0:raise ValueError("Price cannot be negative")# 尝试设置负价格会引发异常
product = Product(name='Test', price=-10)  # 引发 ValueError

5.3 多数据库支持

python

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker# 主数据库
master_engine = create_engine('postgresql://master.db')
MasterSession = sessionmaker(bind=master_engine)# 从数据库
slave_engine = create_engine('postgresql://slave.db')
SlaveSession = sessionmaker(bind=slave_engine)# 根据操作类型选择会话
def get_session(read_only=False):return SlaveSession() if read_only else MasterSession()# 使用示例
with get_session(read_only=True) as session:products = session.query(Product).all()  # 从从库读取

6. ORM 性能优化

6.1 批量操作

python

# 低效方式
for i in range(1000):product = Product(name=f'Product {i}', price=i*10)session.add(product)session.commit()  # 每次提交# 高效方式
session.bulk_insert_mappings(Product, [{'name': f'Product {i}', 'price': i*10} for i in range(1000)
])
session.commit()  # 一次提交

6.2 延迟加载 vs 立即加载

python

# 默认是延迟加载
author = session.query(Author).first()
# 访问 books 属性时会触发新的查询
print(author.books)  # 执行新的查询# 使用 joinedload 立即加载
from sqlalchemy.orm import joinedloadauthor = session.query(Author).options(joinedload(Author.books)).first()
# books 已经被加载
print(author.books)  # 不会执行新的查询

6.3 只加载需要的列

python

# 只加载 id 和 name 列
products = session.query(Product.id, Product.name).all()

7. 常见问题与解决方案

7.1 N+1 查询问题

问题:获取一个列表,然后对每个元素访问关联属性,导致大量查询。

解决方案:使用 joinedloadsubqueryload

python

from sqlalchemy.orm import subqueryload# 不好的方式 (N+1 查询)
authors = session.query(Author).all()
for author in authors:print(author.books)  # 每个 author 都会触发一个查询# 好的方式 (2 个查询)
authors = session.query(Author).options(subqueryload(Author.books)).all()
for author in authors:print(author.books)  # 不会触发新查询

7.2 长事务问题

问题:事务打开时间过长,导致数据库连接被占用。

解决方案:合理划分事务范围。

python

# 不好的方式
with session.begin():# 长时间操作process_large_dataset(session)# 其他操作...# 好的方式
for chunk in get_data_chunks():with session.begin():process_chunk(session, chunk)

8. ORM 最佳实践

  1. 合理使用 ORM:简单查询使用 ORM,复杂查询可以考虑直接使用 SQL

  2. 注意会话生命周期:避免长时间持有会话

  3. 批量操作:大量数据操作时使用批量方法

  4. 选择性加载:只加载需要的列和关联

  5. 索引优化:确保数据库表有适当的索引

  6. 监控性能:使用 SQL 日志和性能分析工具

9. 总结

Python ORM 提供了强大的数据库操作能力,可以显著提高开发效率。选择适合项目规模的 ORM 框架,合理使用其特性,并注意性能优化,可以构建出既高效又易于维护的数据库访问层。

http://www.lqws.cn/news/593875.html

相关文章:

  • UI前端大数据可视化实战技巧分享:如何选择合适的颜色与图表类型?
  • MATLAB构建capm和三因子模型
  • t检验​、​z检验、χ²检验中的P值
  • rabbitmq动态创建交换机、队列、动态绑定,销毁
  • 企业上网行为管理:零信任安全产品的对比分析
  • go语言安装达梦数据完整教程
  • 大数据在UI前端的应用创新研究:基于自然语言处理的用户意图识别
  • Spring生态的核心组件演进
  • 21、鸿蒙学习——使用App Linking实现应用间跳转
  • 推客系统小程序终极指南:从0到1构建自动裂变增长引擎,实现业绩10倍增长!
  • 使用tensorflow的线性回归的例子(二)
  • 【第二章:机器学习与神经网络概述】04.回归算法理论与实践 -(2)支持向量回归(SVR)
  • linux魔术字定位踩内存总结
  • GORM 删除的重要特性:软删除实践案例(优化版)
  • 前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
  • React:利用React.memo和useCallback缓存弹窗组件
  • Oracle 常用函数
  • 设置linux静态IP
  • 测试第六讲-测试模型分类
  • RabbitMQ - SpringAMQP及Work模型
  • 信息化项目验收,软件工程评审和检查表单
  • Qt中使用QSettings数据或结构体到INI文件
  • 边缘人工智能与医疗AI融合发展路径:技术融合与应用前景(下)
  • 区块链存证:数字时代的法律盾牌还是技术乌托邦?
  • 数据结构day5——队列和树
  • 县级智慧水务一体化方案及落地案例PPT(39页)
  • 8.Docker镜像讲解
  • 高强螺栓的计算与选用
  • 深入金融与多模态场景实战:金融文档分块技术与案例汇总
  • Qt时间显示按钮功能详解