简体   繁体   English

为什么sqlalchemy使用DeclarativeMeta类继承将对象映射到表

[英]Why does sqlalchemy use DeclarativeMeta class inheritance to map objects to tables

I'm learning sqlalchemy's ORM and I'm finding it very confusing / unintuitive.我正在学习 sqlalchemy 的 ORM,我发现它非常混乱/不直观。 Say I want to create a User class and corresponding table.. I think I should do something like假设我想创建一个 User 类和相应的表..我想我应该做类似的事情

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()

Here I我在这

  1. create an Engine .创建一个引擎 My understanding is that the engine is like the front-line communicator between my code and the database.我的理解是,引擎就像我的代码和数据库之间的前线通信器。
  2. create a DeclarativeMeta , a metaclass whose job I think is to keep track of a mapping between my Python classes and my SQL tables创建一个DeclarativeMeta ,一个元类,我认为它的工作是跟踪我的 Python 类和我的 SQL 表之间的映射
  3. create a User class创建一个用户类
  4. initialize my database and tables with Base.metadata.create_all(engine)使用Base.metadata.create_all(engine)初始化我的数据库和表
  5. create a Session metaclass创建一个会话元类
  6. create a Session instance, session1创建一个 Session 实例session1
  7. create a User instance, user1创建一个用户实例, user1

The thing I find quite confusing here is the Base superclass.我在这里发现相当混乱的是 Base 超类。 What is the benefit to using it as opposed to doing something like engine.create_table(User) ?与做诸如engine.create_table(User)类的事情相比,使用它有什么好处?

Additionally, if we don't need a Session to create the database and insert tables, why do we need a Session to insert records?另外,如果我们不需要 Session 来创建数据库和插入表,为什么我们需要一个 Session 来插入记录?

SQLAlchemy needs a mechanism to hook the classes being mapped to the database rows. SQLAlchemy 需要一种机制来挂钩映射到数据库行的类。 Basically, you have to tell it:基本上,你必须告诉它:

Use the class User as a mapped class for the table some_table.使用类 User 作为表 some_table 的映射类。 One way to do it is to use a common base class - declarative base.一种方法是使用公共基类 - 声明性基类。 Another way would be calling a function to register you class into the mapper.另一种方法是调用一个函数将您的类注册到映射器中。 This declarative base used to be an extension of sqlalchemy IIRC but later it became a standard.这个声明性基础曾经是 sqlalchemy IIRC 的扩展,但后来成为标准。

Now, having a common base makes perfect sense for me, because I do not have to make an extra step to call a function to register the mapping.现在,拥有一个共同的基础对我来说非常有意义,因为我不必执行额外的步骤来调用函数来注册映射。 Instead, whatever I inherit from the declarative base is automatically mapped.相反,我从声明性基础继承的任何内容都会自动映射。 Both attitudes can work in general.这两种态度一般都可以奏效。

Engine is able to give you connections and can take care of connection pooling.引擎能够为您提供连接并可以处理连接池。 Connection is able to run things on the database.连接能够在数据库上运行东西。 No ORM as yet.还没有 ORM。 With a connection, you can create and run queries using QL (query language), but you have no mapping of database data to python objects.通过连接,您可以使用 QL(查询语言)创建和运行查询,但您无法将数据库数据映射到 Python 对象。

Session uses a connection and takes care of ORM. Session 使用连接并处理 ORM。 Better read the docs here, but the simplest case is:最好在这里阅读文档,但最简单的情况是:

user1.name = "Different Fred"

That's it.就是这样。 It will generate and execute the SQL at the right moment.它将在适当的时候生成并执行 SQL。 Really, read the docs.真的,阅读文档。

Now, you can create a table only with a connection, as it does not make much sense to include the session in the process, because session takes care of the current mapping session.现在,您可以仅使用连接创建表,因为在进程中包含会话没有多大意义,因为会话负责当前的映射会话。 There is nothing to map if you do not physically have the table yet.如果您还没有物理上的桌子,则没有什么可映射的。 So you create the tables with the connection, then you can make a session and use mapping.因此,您使用连接创建表,然后您可以进行会话并使用映射。 Also, tables creation is usually a once-off action done separately from the normal program run (at least create_all).此外,表创建通常是与正常程序运行(至少是 create_all)分开完成的一次性操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM