为什么sqlalchemy使用DeclarativeMeta class 继承将对象映射到表
Why does sqlalchemy use DeclarativeMeta class inheritance to map objects to tables
我正在学习 sqlalchemy 的 ORM,我发现它非常混乱/不直观。假设我想创建一个用户 class 和相应的 table.. 我想我应该做类似
的事情
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///todooo.db")
Base = declarative_base()
class User(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
Base.metadata.create_all(engine)
Session = sessionmaker(bind = engine)
session1 = Session()
user1 = User(name='fred')
session1.add(user1)
session1.commit()
我在这里
- 创建一个引擎。我的理解是引擎就像我的代码和数据库之间的前线通信器。
- 创建一个 DeclarativeMeta,一个元class,我认为它的工作是跟踪我的 Python classes 之间的映射和我的 SQL tables
- 创建用户 class
- 用
Base.metadata.create_all(engine)
初始化我的数据库和 tables
- 创建会话元class
- 创建会话实例,
session1
- 创建一个用户实例,
user1
我觉得这里很混乱的是 Base superclass。与 engine.create_table(User)
之类的操作相比,使用它有什么好处?
另外,如果我们不需要Session来创建数据库和插入tables,为什么我们需要Session来插入记录?
SQLAlchemy 需要一种机制来挂钩映射到数据库行的 classes。基本上,你必须告诉它:
将 class 用户用作 table some_table 的映射 class。一种方法是使用通用基础 class - 声明性基础。另一种方法是调用函数将您 class 注册到映射器中。这个声明性基础曾经是 sqlalchemy IIRC 的扩展,但后来成为标准。
现在,拥有一个共同的基础对我来说非常有意义,因为我不必执行额外的步骤来调用函数来注册映射。相反,我从声明性基础继承的任何内容都会自动映射。这两种态度一般都可以奏效。
引擎能够为您提供连接并负责连接池。连接能够 运行 数据库上的东西。目前还没有 ORM。通过连接,您可以使用 QL(查询语言)创建和 运行 查询,但您没有数据库数据到 python 对象的映射。
会话使用连接并负责 ORM。最好阅读此处的文档,但最简单的情况是:
user1.name = "Different Fred"
就是这样。它会在适当的时候生成并执行 SQL。真的,请阅读文档。
现在,您可以仅使用连接创建 table,因为将会话包含在进程中没有多大意义,因为会话负责当前的映射会话。如果您还没有实际拥有 table,则没有什么可映射的。因此,您使用连接创建 tables,然后您可以建立会话并使用映射。此外,table 的创建通常是与正常程序 运行(至少 create_all)分开完成的一次性操作。
我正在学习 sqlalchemy 的 ORM,我发现它非常混乱/不直观。假设我想创建一个用户 class 和相应的 table.. 我想我应该做类似
的事情from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine("sqlite:///todooo.db")
Base = declarative_base()
class User(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
Base.metadata.create_all(engine)
Session = sessionmaker(bind = engine)
session1 = Session()
user1 = User(name='fred')
session1.add(user1)
session1.commit()
我在这里
- 创建一个引擎。我的理解是引擎就像我的代码和数据库之间的前线通信器。
- 创建一个 DeclarativeMeta,一个元class,我认为它的工作是跟踪我的 Python classes 之间的映射和我的 SQL tables
- 创建用户 class
- 用
Base.metadata.create_all(engine)
初始化我的数据库和 tables
- 创建会话元class
- 创建会话实例,
session1
- 创建一个用户实例,
user1
我觉得这里很混乱的是 Base superclass。与 engine.create_table(User)
之类的操作相比,使用它有什么好处?
另外,如果我们不需要Session来创建数据库和插入tables,为什么我们需要Session来插入记录?
SQLAlchemy 需要一种机制来挂钩映射到数据库行的 classes。基本上,你必须告诉它:
将 class 用户用作 table some_table 的映射 class。一种方法是使用通用基础 class - 声明性基础。另一种方法是调用函数将您 class 注册到映射器中。这个声明性基础曾经是 sqlalchemy IIRC 的扩展,但后来成为标准。
现在,拥有一个共同的基础对我来说非常有意义,因为我不必执行额外的步骤来调用函数来注册映射。相反,我从声明性基础继承的任何内容都会自动映射。这两种态度一般都可以奏效。
引擎能够为您提供连接并负责连接池。连接能够 运行 数据库上的东西。目前还没有 ORM。通过连接,您可以使用 QL(查询语言)创建和 运行 查询,但您没有数据库数据到 python 对象的映射。
会话使用连接并负责 ORM。最好阅读此处的文档,但最简单的情况是:
user1.name = "Different Fred"
就是这样。它会在适当的时候生成并执行 SQL。真的,请阅读文档。
现在,您可以仅使用连接创建 table,因为将会话包含在进程中没有多大意义,因为会话负责当前的映射会话。如果您还没有实际拥有 table,则没有什么可映射的。因此,您使用连接创建 tables,然后您可以建立会话并使用映射。此外,table 的创建通常是与正常程序 运行(至少 create_all)分开完成的一次性操作。