为什么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()

我在这里

  1. 创建一个引擎。我的理解是引擎就像我的代码和数据库之间的前线通信器。
  2. 创建一个 DeclarativeMeta,一个元class,我认为它的工作是跟踪我的 Python classes 之间的映射和我的 SQL tables
  3. 创建用户 class
  4. Base.metadata.create_all(engine)
  5. 初始化我的数据库和 tables
  6. 创建会话元class
  7. 创建会话实例,session1
  8. 创建一个用户实例,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)分开完成的一次性操作。