Python SQLAlchemy ORM:从Mapping到Declarative的演进
本文深入解析Python SQLAlchemy中ORM映射的两种实现方式。首先介绍传统的mapper函数映射机制,通过定义Table、类及mapper关联实现对象与数据表对应;随后重点讲解Declarative声明式系统,展示如何继承Base类简化映射配置。通过对比两种方式的代码结构,帮助开发者理解ORM底层原理并选择合适方案。
SQLAlchemy ORM映射概述
前文曾介绍过SQLAlchemy中的Engine和Connection对象,它们主要用于处理原生SQL语句。而ORM(Object Relational Mapper,对象关系映射)则提供了一种面向对象的操作数据库表数据的技术思路。简而言之,ORM建立了Python对象与数据库表之间的映射关系。
在早期的SQLAlchemy版本中,Python对象与数据库中每条记录的映射是通过一个特定的mapping函数来实现的。
传统Mapping函数映射机制
首先通过一个具体示例来展示这一过程:
from sqlalchemy import Table, MetaData, Column, Integer, String,
from sqlalchemy.orm import mapper
# 数据库的元数据,你可以认为它是一个容器,装载了所有的表结构
metadata = MetaData()
# 数据库中的news_article表
article = Table("news_article", metadata,
Column("id", Integer, primary_key=True),
Column("title", String)
)
# 这是一个普通的Article类
class Article:
def __init__(self, title):
self.title = title
# 通过mapper函数进行映射关联
mapper(Article, article)
完成映射关联后,实际使用方式如下例所示:
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
# 通过Artcile类来查询id==4554的记录,这完全是用面向对象的方式执行sql了
# 返回结果就是Article的实例对象
result = session.query(Article).filter(Article.id==4554).first()
print(result.id) # 4554
print(result.title) # xxxxxxxxx
经过mapper函数映射后,通过query查询返回的结果会自动构建为一个Article对象,并具备id属性。这正是ORM技术的核心优势所在。
Declarative声明式系统
而新版ORM映射不再需要手动使用mapping函数来关联Table与类之间的关系,可以直接通过声明(Declarative)系统来定义类。该类直接映射到数据库表,Declarative将Table、mapper以及类三者整合在一起进行声明,从而实现了ORM映射。具体示例如下:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Article(Base):
__tablename__ = 'news_article'
id = Column(Integer, primary_key=True)
title = Column(String(50))
这种方式是否更加简洁?不再需要单独定义Table,也无需调用mapper函数,仅需定义一个继承自基类Base的类即可。Base即为声明系统,由此完成了Table与类之间的映射关系,其背后的操作均由declarative_base工厂方法构造的声明系统自动完成。
我们将此类称为映射类,它持有对Table和mapper函数的引用。
>>> print(Article.__table__)
news_article
>>>print(Article.__mapper__)
Mapper|Article|news_article
# 前面将的metadata 可以通过 Base 获取
>>>print(Base.metadata)
MetaData(bind=None)
MetaData的作用
那么MetaData的作用是什么?可以通过它来创建或删除数据库表。
以上即为本文的全部内容,希望这对大家的学习有所帮助,同时也欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









