SQLAlchemy ORM - 声明映射
在本文中,我们将看到如何在Python中使用 SQLAlchemy 声明映射。
您将需要一个数据库(MySQL、PostgreSQL、SQLite 等)才能使用。由于我们将在这篇文章中使用 MySQL,因此我们还将在Python中为 MySQL 安装 SQL 连接器。但是,除了 SQL 连接器之外,没有任何代码实现会随着数据库的变化而变化。
pip install pymysql
我们将使用 MySQL 中的示例sakila 数据库。在本文中,我们将介绍 2 个示例。在这两个示例中,我们将声明 sakila 数据库中演员表的映射。如果您没有 sakila 数据库并且想在不安装它的情况下继续阅读本文,那么使用下面提到的链接中的 SQL 脚本来创建所需的模式和参与者表以及记录。
使用的数据库: Sakila 演员表脚本
我们在以下两个示例中查看的 SQL 查询是 -
SELECT COUNT(*) FROM sakila.`actor`;
SQLAlchemy Core使用以对象为中心的视图,它将模式与业务对象封装在一起。这是一个更 Pythonic 的实现,其中表使用Python中的面向对象的类进行映射。在 SQLAlchemy 中,我们可以通过两种不同的方式声明映射器配置,即声明式和经典/命令式。 “ Classical ”或“ Imperative ”风格是SQLAlchemy的原始映射API,而“ Declarative ”是建立在“Classical”之上的更丰富、更简洁的系统。让我们看看如何使用这两种方式声明映射。
声明式映射:
对于下面的示例,我们使用了声明式映射。在此,我们创建了一个继承自 `declarative_base()` 方法的 Actor 类。然后我们提供示例中提到的表名和模式名。请注意,MySQL 数据库中可能不需要模式名称(因为 MySQL 中的数据库和模式名称最终相同),但可以作为模式和数据库不同的 PostgreSQL 数据库的方便设置。我们使用 `Actor` 类映射了 sakila 数据库中的 `actor` 表。为了测试我们的映射是否正常工作,我们创建了一个 sqlalchemy 引擎连接,并使用此连接使用 SQLAlchemy 的 ORM 方法查询数据库。在提供的示例中,我们正在获取“actor”表中的记录计数。我们还可以查看`Actor`类的数据类型;它代表 SQLAlchemy 的 ORM 对象。
Python3
from sqlalchemy.orm import sessionmaker
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# MAPPING CLASS ACTOR USING DECLARATIVE MAPPING
class Actor(Base):
__table_args__ = {'schema': 'sakila'}
__tablename__ = 'actor'
actor_id = db.Column(db.SmallInteger, autoincrement=True, primary_key=True)
first_name = db.Column(db.String(45), nullable=False)
first_name = db.Column(db.String(45), nullable=False)
last_update = db.Column(db.TIMESTAMP, nullable=False, server_default=db.text(
'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
Session = sessionmaker(bind=engine)
session = Session()
# SELECT COUNT(*) FROM Actor
result = session.query(Actor).count()
print("Count of Records in Actor Table:", result)
print("Type of Actor Class:", type(Actor))
Python3
from sqlalchemy.orm import sessionmaker
import sqlalchemy as db
from sqlalchemy.orm import mapper
# CREATE THE METADATA OBJECT REQUIRED TO CREATE THE TABLE
metadata = db.MetaData()
# DEFINE THE ACTOR TABLE USING SQLALCHEMY CORE
actor = db.Table(
'actor',
metadata,
db.Column('actor_id', db.SmallInteger,
autoincrement=True, primary_key=True),
db.Column('first_name', db.String(45), nullable=False),
db.Column('last_name', db.String(45), nullable=False),
db.Column('last_update', db.TIMESTAMP, nullable=False, server_default=db.text(
'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
)
# MAPPING CLASS ACTOR USING CLASSICAL MAPPING
class Actor(object):
def __init__(self, first_name, last_name) -> None:
self.first_name = first_name
self.last_name = last_name
mapper(Actor, actor)
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
Session = sessionmaker(bind=engine)
session = Session()
# SELECT COUNT(*) FROM Actor
result = session.query(Actor).count()
print("Count of Records in Actor Table:", result)
print("Type of Actor Class:", type(Actor))
输出:
Count of Records in Actor Table: 200
Type of Actor Class:
经典/命令式映射:
第一个示例中显示的声明式映射建立在经典或命令式映射之上。命令式映射使用 SQLAlchemy 的 Core 方法来定义数据库,然后使用 SQLAlchemy ORM 的`mapper()` 方法进行环绕,以便映射开始 ORM 注册表对象,该对象维护一组映射的类(就像声明式映射一样) .您可以比较这两个示例,以发现一旦我们创建了这些映射器对象,我们就可以使用相同的 ORM 语法来查询数据库。在这个例子中,我们再次从 `sakila` 数据库中的 `actor` 表中获取记录数。值得一提的是,在这个例子中,`Actor` 类也代表了 SQLAlchemy 的 ORM 对象。
Python3
from sqlalchemy.orm import sessionmaker
import sqlalchemy as db
from sqlalchemy.orm import mapper
# CREATE THE METADATA OBJECT REQUIRED TO CREATE THE TABLE
metadata = db.MetaData()
# DEFINE THE ACTOR TABLE USING SQLALCHEMY CORE
actor = db.Table(
'actor',
metadata,
db.Column('actor_id', db.SmallInteger,
autoincrement=True, primary_key=True),
db.Column('first_name', db.String(45), nullable=False),
db.Column('last_name', db.String(45), nullable=False),
db.Column('last_update', db.TIMESTAMP, nullable=False, server_default=db.text(
'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
)
# MAPPING CLASS ACTOR USING CLASSICAL MAPPING
class Actor(object):
def __init__(self, first_name, last_name) -> None:
self.first_name = first_name
self.last_name = last_name
mapper(Actor, actor)
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
Session = sessionmaker(bind=engine)
session = Session()
# SELECT COUNT(*) FROM Actor
result = session.query(Actor).count()
print("Count of Records in Actor Table:", result)
print("Type of Actor Class:", type(Actor))
输出:
Count of Records in Actor Table: 200
Type of Actor Class: