SQLAlchemy_定义(一对一/一对多/多对多)关系

举报
云物互联 发表于 2021/08/06 00:51:21 2021/08/06
【摘要】 目录 目录Basic Relationship PatternsOne To ManyOne To OneMany To Many Basic Relationship Patterns 基本关系模式 The imports used for each of the following sections is as follows: 下列...

目录

Basic Relationship Patterns

基本关系模式
The imports used for each of the following sections is as follows:
下列的 import 语句,应用到接下来所有的代章节中:

from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
  
 

One To Many

A one to many relationship places a foreign key on the child table referencing the parent.
表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类。
relationship() is then specified on the parent, as referencing a collection of items represented by the child:
然后,在父表类中通过 relationship() 方法来引用子表的类:

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child") # 在父表类中通过 relationship() 方法来引用子表的类集合

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id')) # 在子表类中通过 foreign key (外键)引用父表的参考字段
  
 

To establish a bidirectional relationship in one-to-many, where the “reverse” side is a many to one,
一对多的关系中建立双向的关系,这样的话在对方看来这就是一个多对一的关系,
specify an additional relationship() and connect the two using the relationship.back_populates parameter:
在子表类中附加一个 relationship() 方法,并且在双方的 relationship() 方法中使用 relationship.back_populates 方法参数:

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child", back_populates="parent")

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id')) parent = relationship("Parent", back_populates="children") # 子表类中附加一个 relationship() 方法 # 并且在(父)子表类的 relationship() 方法中使用 relationship.back_populates 参数
  
 

Child will get a parent attribute with many-to-one semantics.
这样的话子表将会在多对一的关系中获得父表的属性

Alternatively, the backref option may be used on a single relationship() instead of using back_populates:
或者,可以在单一的 relationship() 方法中使用 backref 参数来代替 back_populates 参数:

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child", backref="parent")

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id'))
  
 

One To One

One To One is essentially a bidirectional relationship with a scalar attribute on both sides.
一对一是两张表之间本质上的双向关系。
To achieve this, the uselist flag indicates the placement of a scalar attribute instead of a collection on the “many” side of the relationship.
要做到这一点,只需要在一对多关系基础上的父表中使用 uselist 参数来表示。
To convert one-to-many into one-to-one:

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child = relationship("Child", uselist=False, back_populates="parent")

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id')) parent = relationship("Parent", back_populates="child")
  
 

To convert many-to-one into one-to-one:

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", back_populates="parent")

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent = relationship("Parent", back_populates="child", uselist=False)
  
 

As always, the relationship.backref and backref() functions may be used in lieu of the relationship.back_populates approach; to specify uselist on a backref, use the backref() function:
同样的,可以使用下面这种方式:

from sqlalchemy.orm import backref

class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref=backref("parent", uselist=False))

class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id'))
  
 

Many To Many

Many to Many adds an association table between two classes.
多对多关系会在两个类之间增加一个关联的表。
The association table is indicated by the secondary argument to relationship().
这个关联的表在 relationship() 方法中通过 secondary 参数来表示。
Usually, the Table uses the MetaData object associated with the declarative base class,
通常的,这个表会通过 MetaData 对象来与声明基类关联,
so that the ForeignKey directives can locate the remote tables with which to link:
所以这个 ForeignKey 指令会使用链接来定位到远程的表:

# 多对多关系中的两个表之间的一个关联表
association_table = Table('association', Base.metadata, Column('left_id', Integer, ForeignKey('left.id')), Column('right_id', Integer, ForeignKey('right.id'))
)

class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary=association_table) # 在父表中的 relationship() 方法传入 secondary 参数,其值为关联表的表名

class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True)
  
 

For a bidirectional relationship, both sides of the relationship contain a collection.
双向关系中,两个表类都会包含这个集合。
Specify using relationship.back_populates, and for each relationship() specify the common association table:
指定使用 relationship.back_populates 参数,并且为每一个 relationship() 方法指定共用的关联表:

 association_table = Table('association', Base.metadata, Column('left_id', Integer, ForeignKey('left.id')), Column('right_id', Integer, ForeignKey('right.id'))
)

class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship( "Child", secondary=association_table, back_populates="parents")

class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True) parents = relationship( "Parent", secondary=association_table, back_populates="children")
  
 

When using the backref parameter instead of relationship.back_populates, the backref will automatically use the same secondary argument for the reverse relationship:
当在父表类的 relationship() 方法中使用 backref参数代替 relationship.back_populates 时,backref 会自动的为子表类加载同样的 secondary 参数。

association_table = Table('association', Base.metadata, Column('left_id', Integer, ForeignKey('left.id')), Column('right_id', Integer, ForeignKey('right.id'))
)

class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary=association_table, backref="parents")

class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True)
  
 

The secondary argument of relationship() also accepts a callable that returns the ultimate argument,
secondary 参数还能够接收一个可调函数的最终返回值,
which is evaluated only when mappers are first used. Using this, we can define the association_table at a later point, as long as it’s available to the callable after all module initialization is complete:

class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary=lambda: association_table, backref="parents")
  
 

With the declarative extension in use, the traditional “string name of the table” is accepted as well, matching the name of the table as stored in Base.metadata.tables:

class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary="association", backref="parents")
  
 

文章来源: is-cloud.blog.csdn.net,作者:范桂飓,版权归原作者所有,如需转载,请联系作者。

原文链接:is-cloud.blog.csdn.net/article/details/52445093

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。