SQLAlchemy – 映射表列
在本文中,我们将看到如何在Python中使用 SQLAlchemy 映射表列。
您将需要一个数据库(MySQL、PostgreSQL、SQLite 等)才能使用。由于我们将在这篇文章中使用 MySQL,因此我们还将在Python中为 MySQL 安装 SQL 连接器。但是,除了 SQL 连接器之外,没有任何代码实现会随着数据库的变化而变化。
pip install pymysql
我们将使用 MySQL 中的示例 sakila 数据库。本文中涉及的所有示例都将使用 sakila 数据库中的 actor 表。如果您没有 sakila 数据库并且想在不安装它的情况下继续阅读本文,那么使用下面提到的链接中的 SQL 脚本来创建所需的模式和参与者表以及记录。
使用的数据库: Sakila 演员表脚本
我们将在下面提到的每个示例中引用相同的 SQL 查询 -
SELECT first_name FROM sakila.actor LIMIT 1;
我们可以在 SQLAlchemy 中映射列的不同方式是——
- 将列直接映射到属性名称
- 映射列与属性名称不同
- 使用反射映射列
- 使用前缀映射列
将列直接映射到属性名称
在下面的示例中,列映射是通过将每个表列映射为类属性来完成的。每个属性都具有与其所代表的相应表列相同的名称。然后我们在 MySQL 中建立连接到 sakila 数据库的 SQLAlchemy 引擎。然后创建一个会话对象来查询数据库。使用这个会话对象,我们将查询 `actor` 表中的第一条记录。我们通过访问“result”对象的“first_name”属性来获取第一条记录的“first_name”列的值。这表明,actor 表的列映射到 Actor 类的属性。
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# MAPPING TABLE ACTOR
class Actor(Base):
__tablename__ = 'actor'
actor_id = db.Column(db.SmallInteger, autoincrement=True, primary_key=True)
first_name = db.Column(db.String(45), nullable=False)
last_name = db.Column(db.String(45), nullable=False)
last_update = db.Column(db.TIMESTAMP, nullable=False)
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT * FROM sakila.actor LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result.first_name)
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# MAPPING TABLE ACTOR
class Actor(Base):
__tablename__ = 'actor'
id = db.Column('actor_id', db.SmallInteger, autoincrement=True,
primary_key=True)
fname = db.Column('first_name', db.String(45), nullable=False)
lname = db.Column('last_name', db.String(45), nullable=False)
update_on = db.Column('last_update', db.TIMESTAMP, nullable=False)
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT * FROM sakila.actor LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result.fname)
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
class Actor(Base):
__table__ = db.Table("actor", Base.metadata, autoload_with=engine)
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT COUNT(*) FROM Table LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result.first_name)
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
class Actor(Base):
__table__ = db.Table("actor", Base.metadata, autoload_with=engine)
__mapper_args__ = {'column_prefix': '_'}
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT COUNT(*) FROM Table LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result._first_name)
输出:
First Name (Record 1): PENELOPE
映射列与属性名称不同
这与第一个示例类似,只是稍作改动。此示例中提到的属性名称与列名称不同。这可以通过在 `Column()` 方法中提供一个附加参数来实现。该方法的第一个参数接受实际的列名,这允许使用不同的属性名来引用这些列。如果我们查看最终的 `print()` 方法,演员表中第一条记录的名字是使用 `fname` 属性引用的,而不是第一个示例中看到的 `first_name` 或实际列名。
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# MAPPING TABLE ACTOR
class Actor(Base):
__tablename__ = 'actor'
id = db.Column('actor_id', db.SmallInteger, autoincrement=True,
primary_key=True)
fname = db.Column('first_name', db.String(45), nullable=False)
lname = db.Column('last_name', db.String(45), nullable=False)
update_on = db.Column('last_update', db.TIMESTAMP, nullable=False)
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT * FROM sakila.actor LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result.fname)
输出:
First Name (Record 1): PENELOPE
使用反射映射列
在前面的两个示例中,我们需要使用类及其属性将每一列与表显式映射。在这种方法中,我们不需要单独提供每个表列的这种显式映射。使用反射,此任务通过提供元数据对象和 SQLAlchemy 引擎连接自动完成。在 `__table__` 属性中。然后,我们可以使用引擎和会话对象来查询参与者表以获取名字,就像在前面的示例中所做的那样,使用列名“first_name”作为属性名本身。
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
class Actor(Base):
__table__ = db.Table("actor", Base.metadata, autoload_with=engine)
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT COUNT(*) FROM Table LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result.first_name)
输出:
First Name (Record 1): PENELOPE
使用前缀映射列
前缀的使用很少见,但仍然可以在某些用例中找到。在这个例子中,可以看出我们使用了一个额外的属性`__mapper_args__`,它是一个Python字典。它提供了一个作为“column_prefix”的键和一个“_”的值。这意味着我们要在所有列名或属性名前加上下划线。出于这个原因,我们使用 `_first_name` 而不是 `first_name` 作为相应列的属性。
Python3
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
class Actor(Base):
__table__ = db.Table("actor", Base.metadata, autoload_with=engine)
__mapper_args__ = {'column_prefix': '_'}
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
# SELECT COUNT(*) FROM Table LIMIT 1;
result = session.query(Actor).first()
# DISPLAY FIRST NAME OF FIRST RECORD IN ACTOR TABLE
print("First Name (Record 1):", result._first_name)
输出:
First Name (Record 1): PENELOPE