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

简介: 目录目录Basic Relationship PatternsOne To ManyOne To OneMany To ManyBasic Relationship Patterns基本关系模式 The imports used for...

目录

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")
相关文章
|
6月前
|
JSON Java API
Java一分钟之-JPA实体关系:一对一, 一对多, 多对多
【6月更文挑战第14天】Java Persistence API (JPA) 的 ORM 规范简化了数据库操作,重点是实体关系映射。本文讨论了三种主要关系:一对一、一对多和多对多。对于每种关系,都指出了常见问题(如循环引用、懒加载异常)和避免策略(使用注解解决循环引用,明确级联操作边界等)。同时,提供了示例代码以展示如何在实践中设置这些关系。理解并妥善处理这些问题能提升开发效率和数据准确性。
312 1
|
7月前
|
SQL 缓存 Java
Hibernae - 双向多对一关联关系映射
Hibernae - 双向多对一关联关系映射
55 0
|
关系型数据库 MySQL 数据库
SQLAlchemy关联表一对多关系的详解
SQLAlchemy关联表一对多关系的详解
|
存储 Java 数据库
JPA实现多对多关系
JPA实现多对多关系
175 0
|
Java 数据库连接
hibernate一对多关系操作
hibernate一对多关系操作
171 1
hibernate一对多关系操作
|
存储 关系型数据库 数据库
[译] 如何用 Room 处理一对一,一对多,多对多关系?
[译] 如何用 Room 处理一对一,一对多,多对多关系?
[译] 如何用 Room 处理一对一,一对多,多对多关系?
|
存储 Java 数据库连接
Hibernate的一对多映射的单向关联和双向关联(九)
Hibernate的一对多映射的单向关联和双向关联(九)
137 0
Hibernate的一对多映射的单向关联和双向关联(九)
|
开发者
多对多关系 | 学习笔记
快速学习多对多关系。
150 0
多对多关系 | 学习笔记
举一个多对多关联的例子,并说明如何实现多对多关联映射
例如:商品和订单、学生和课程都是典型的多对多关系。可以在实体类上通过@ManyToMany注解配置多对多关联或者通过映射文件中的和标签配置多对多关联,但是实际项目开发中,很多时候都是将多对多关联映射转换成两个多对一关联映射来实现的。
1529 0
|
Java 数据库连接 关系型数据库