📜  SQLAlchemy ORM-建立关系

📅  最后修改于: 2020-11-27 07:50:25             🧑  作者: Mango


该会话描述了另一个表的创建,该表与我们数据库中已经存在的表相关。客户表包含客户的主数据。现在,我们需要创建发票表,其中可能包含任意数量的属于客户的发票。这是一对多关系的情况。

使用声明式,我们定义此表及其映射的类Invoices,如下所示-

from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
engine = create_engine('sqlite:///sales.db', echo = True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import relationship

class Customer(Base):
   __tablename__ = 'customers'

   id = Column(Integer, primary_key = True)
   name = Column(String)
   address = Column(String)
   email = Column(String)

class Invoice(Base):
   __tablename__ = 'invoices'
   
   id = Column(Integer, primary_key = True)
   custid = Column(Integer, ForeignKey('customers.id'))
   invno = Column(Integer)
   amount = Column(Integer)
   customer = relationship("Customer", back_populates = "invoices")

Customer.invoices = relationship("Invoice", order_by = Invoice.id, back_populates = "customer")
Base.metadata.create_all(engine)

这将向SQLite引擎发送一个CREATE TABLE查询,如下所示-

CREATE TABLE invoices (
   id INTEGER NOT NULL,
   custid INTEGER,
   invno INTEGER,
   amount INTEGER,
   PRIMARY KEY (id),
   FOREIGN KEY(custid) REFERENCES customers (id)
)

我们可以借助SQLiteStudio工具检查在sales.db中是否创建了新表。

Sales.db新表

发票类将ForeignKey构造应用于custid属性。该指令指示此列中的值应被约束为customers表的id列中存在的值。这是关系数据库的核心功能,并且是将表的未连接集合转换为具有丰富重叠关系的“胶水”。

第二个指令,称为Relationship(),告诉ORM应该使用属性Invoice.customer将Invoice类链接到Customer类。 Relationship()使用两个表之间的外键关系来确定此链接的性质,并确定它是一对多的。

一个附加的Relationship()指令放置在Customer映射的类的Customer.invoices属性下。分配了参数Relationship.back_populates来引用互补的属性名称,以便每个Relationship()可以就反向表示的相同关系做出明智的决策。一方面,Invoices.customer引用Invoices实例,另一方面,Customer.invoices引用一系列Customer实例。

关系函数是SQLAlchemy ORM包的Relational API的一部分。它提供了两个映射类之间的关系。这对应于父子关系或关联表关系。

以下是发现的基本关系模式-

一对多

一对多关系是通过子表上的外键来指代父级。然后在父项上指定Relationship(),以引用由子项表示的项的集合。 Relationship.back_populates参数用于建立一对多的双向关系,其中“反面”是一对多。

多对一

另一方面,“多对一”关系在父表中放置了一个外键来引用该子项。在父级上声明relationship(),将在该父级上创建新的标量持有属性。这里,relationship.back_populates参数再次用于双向行为。

一对一

一对一关系本质上是双向关系。 uselist标志指示在关系的“许多”侧标量属性的位置,而不是集合。要将一对多关系转换为一对一关系,请将uselist参数设置为false。

多对多

通过添加与两个类相关的关联表(通过使用外键定义属性)来建立多对多关系。它由Relationship()的辅助参数指示。通常,表使用与声明性基类关联的MetaData对象,以便ForeignKey指令可以找到要链接的远程表。每个Relationship()的Relationship.back_populates参数建立双向关系。关系的双方都包含一个集合。