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

  • 目录
  • Basic Relationship Patterns
  • One To Many
  • One To One
  • Many To Many

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 specifyuselist 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 指令会使用链接来定位到远程的表:

定义中间表可以定义中间关系表相关的类,也可以直接通过Base.metdata生成对应关系表对象,不过基于code first准则,还是推荐将中间关系写成类。

构建第三张关系类实现多对多。

Base = declarative_base() #生成sqlorm基础类

class HostUserToGroup(Base):
    __tablename__ = ‘hostuser_to_group‘ # 表名hostuser_to_group
    nid = Column(Integer, primary_key=True,autoincrement=True)
    hostuser_id = Column(Integer,ForeignKey(‘host_user.id‘),primary_key=True)# 外键关联host_user表的id字段
    group_id = Column(Integer,ForeignKey(‘group.id‘),primary_key=True) # 外键关联group表的id字段

class UserProfileToGroup(Base):
    __tablename__ = ‘userprofile_to_group‘# 表名userprofile_to_group
    nid = Column(Integer, primary_key=True,autoincrement=True)
    userprofile_id = Column(Integer,ForeignKey(‘user_profile.id‘),primary_key=True)# 外键关联user_profile表的id字段
    group_id = Column(Integer,ForeignKey(‘group.id‘),primary_key=True)# 外键关联group表的id字段

class UserProfileToHostUser(Base):
    __tablename__ = ‘userprofile_to_hostuser‘# 表名userprofile_to_hostuser
    nid = Column(Integer, primary_key=True,autoincrement=True)
    userprofile_id = Column(Integer,ForeignKey(‘user_profile.id‘),primary_key=True)# 外键关联user_profile表的id字段
    hostuser_id = Column(Integer,ForeignKey(‘host_user.id‘),primary_key=True)# 外键关联host_user表的id字段

class Host(Base):
    __tablename__ = ‘host‘ #表名host
    id = Column(Integer, primary_key= True, autoincrement= True)# id字段,主键,自动增长
    hostname = Column(String(64),unique= True,nullable= False)# hostname字段,唯一,不能为空
    ip_addr = Column(String(64),unique= True,nullable= False)#ip_addr字段,唯一,不能为空
    port = Column(Integer, default = 22) # port字段,整形,默认22
    def __repr__(self):
        return "<Hostobject: id=%s, hostname=%s, ip_addr=%s, port=%s>" %(self.id, self.hostname, self.ip_addr, self.port)

class Group(Base):
    __tablename__ = ‘group‘ # 表名group
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    name = Column(String(64), unique = True, nullable = False) # name字段,唯一,不为空
    def __repr__(self):
        return "<Group object: id=%s, name=%s>" %(self.id, self.name)

class UserProfile(Base):
    __tablename__ = ‘user_profile‘ # 表名user_profile
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    username = Column(String(64), unique = True, nullable = False) # username字段,唯一,不为空
    password = Column(String(255), nullable = False) # password字段,不为空
    hostusers = relationship(‘HostUser‘, secondary = UserProfileToHostUser.__tablename__, backref = ‘user_profiles‘) # 多对多关联HostUser表类(注意不是表名),中间表类UserProfileToHostUser(注意不是表名),反向字段为user_profiles
    groups = relationship(‘Group‘, secondary = UserProfileToGroup.__tablename__, backref = ‘user_profiles‘) # 多对多关联Group表类(注意不是表名),中间表类UserProfileToGroup(注意不是表名),反向字段为user_profiles

    def __repr__(self):
        return "<UserProfile object: id=%s, username=%s>" %(self.id, self.username)

class HostUser(Base):
    __tablename__ = ‘host_user‘ # 表名host_user
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    host_id = Column(Integer, ForeignKey(‘host.id‘)) # host_id,外键关联host表的id字段
    AuthTypes = [
        (u‘ssh-password‘, u‘SSH/Password‘),
        (u‘ssh-key‘, u‘SSH/Key‘),
    ] # 选项列表
    auth_type = Column(ChoiceType(AuthTypes)) # auth_type字段,只能是选项列表里规定的值
    username = Column(String(64), nullable = True) # username字段,不为空
    password = Column(String(255)) # password字段
    host = relationship(‘Host‘, backref = ‘host_users‘)
    groups = relationship(‘Group‘, secondary = HostUserToGroup.__tablename__, backref = ‘host_users‘) # 多对多关联Group表类(注意不是表名),中间表类HostUserToGroup(注意不是表名),反向字段为host_users
    __table_args = (UniqueConstraint(‘host_id‘, ‘username‘, name = ‘_host_username_uc‘)) # host_id和username组成联合唯一约束

    def __repr__(self):
        return "<HostUser object: id=%s, host_id=%s, username=%s>" %(self.id, self.host_id, self.username)

构建关系表实现多对多实例如下:

from sqlalchemy import create_engine,and_,or_,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,    ForeignKey, UniqueConstraint, DateTime
from sqlalchemy.orm import sessionmaker,relationship
from sqlalchemy_utils import ChoiceType,PasswordType
from datetime import datetime

Base = declarative_base() #生成sqlorm基础类

HostUserToGroup = Table(‘hostuser_to_group‘, Base.metadata,  # 表名hostuser_to_group
    Column(‘hostuser_id‘, ForeignKey(‘host_user.id‘), primary_key = True), # 外键关联host_user表的id字段
    Column(‘group_id‘, ForeignKey(‘group.id‘), primary_key = True), # 外键关联group表的id字段
)

UserProfileToGroup = Table(‘userprofile_to_group‘, Base.metadata, # 表名userprofile_to_group
    Column(‘userprofile_id‘, ForeignKey(‘user_profile.id‘), primary_key = True), # 外键关联user_profile表的id字段
    Column(‘group_id‘, ForeignKey(‘group.id‘), primary_key = True), # 外键关联group表的id字段
)

UserProfileToHostUser = Table(‘userprofile_to_hostuser‘, Base.metadata, # 表名userprofile_to_hostuser
    Column(‘userprofile_id‘, ForeignKey(‘user_profile.id‘), primary_key = True), # 外键关联user_profile表的id字段
    Column(‘hostuser_id‘, ForeignKey(‘host_user.id‘), primary_key = True), # 外键关联host_user表的id字段
)

class Host(Base):
    __tablename__ = ‘host‘ #表名host
    id = Column(Integer, primary_key= True, autoincrement= True)# id字段,主键,自动增长
    hostname = Column(String(64),unique= True,nullable= False)# hostname字段,唯一,不能为空
    ip_addr = Column(String(64),unique= True,nullable= False)#ip_addr字段,唯一,不能为空
    port = Column(Integer, default = 22) # port字段,整形,默认22
    def __repr__(self):
        return "<Hostobject: id=%s, hostname=%s, ip_addr=%s, port=%s>" %(self.id, self.hostname, self.ip_addr, self.port)

class Group(Base):
    __tablename__ = ‘group‘ # 表名group
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    name = Column(String(64), unique = True, nullable = False) # name字段,唯一,不为空
    def __repr__(self):
        return "<Group object: id=%s, name=%s>" %(self.id, self.name)

class UserProfile(Base):
    __tablename__ = ‘user_profile‘ # 表名user_profile
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    username = Column(String(64), unique = True, nullable = False) # username字段,唯一,不为空
    password = Column(String(255), nullable = False) # password字段,不为空
    hostusers = relationship(‘HostUser‘, secondary = UserProfileToHostUser, backref = ‘user_profiles‘) # 多对多关联HostUser表类(注意不是表名),中间表类UserProfileToHostUser(注意不是表名),反向字段为user_profiles
    groups = relationship(‘Group‘, secondary = UserProfileToGroup, backref = ‘user_profiles‘) # 多对多关联Group表类(注意不是表名),中间表类UserProfileToGroup(注意不是表名),反向字段为user_profiles

    def __repr__(self):
        return "<UserProfile object: id=%s, username=%s>" %(self.id, self.username)

class HostUser(Base):
    __tablename__ = ‘host_user‘ # 表名host_user
    id = Column(Integer, primary_key = True) # id字段,主键,自动增长
    host_id = Column(Integer, ForeignKey(‘host.id‘)) # host_id,外键关联host表的id字段
    AuthTypes = [
        (u‘ssh-password‘, u‘SSH/Password‘),
        (u‘ssh-key‘, u‘SSH/Key‘),
    ] # 选项列表
    auth_type = Column(ChoiceType(AuthTypes)) # auth_type字段,只能是选项列表里规定的值
    username = Column(String(64), nullable = True) # username字段,不为空
    password = Column(String(255)) # password字段
    host = relationship(‘Host‘, backref = ‘host_users‘)
    groups = relationship(‘Group‘, secondary = HostUserToGroup, backref = ‘host_users‘) # 多对多关联Group表类(注意不是表名),中间表类HostUserToGroup(注意不是表名),反向字段为host_users
    __table_args = (UniqueConstraint(‘host_id‘, ‘username‘, name = ‘_host_username_uc‘)) # host_id和username组成联合唯一约束

    def __repr__(self):
        return "<HostUser object: id=%s, host_id=%s, username=%s>" %(self.id, self.host_id, self.username)

Linking Relationships with Backref

简单来说, relationship函数是sqlalchemy对关系之间提供的一种便利的调用方式, backref参数则对关系提供反向引用的声明。

The backref keyword argument was first introduced in Object Relational Tutorial, and has been mentioned through- out many of the examples here. What does it actually do ? Let’s start with the canonical User and Address scenario:

from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
__tablename__ = ‘user‘
id = Column(Integer, primary_key=True) name = Column(String)
    addresses = relationship("Address", backref="user")
class Address(Base):
__tablename__ = ‘address‘
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(Integer, ForeignKey(‘user.id‘))

The above configuration establishes a collection of Address objects on User called User.addresses. It also establishes a .user attribute on Address which will refer to the parent User object.

In fact, the backref keyword is only a common shortcut for placing a second relationship() onto the Address mapping, including the establishment of an event listener on both sides which will mirror attribute op- erations in both directions. The above configuration is equivalent to:

from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
    __tablename__ = ‘user‘
    id = Column(Integer, primary_key=True) name = Column(String)
    addresses = relationship("Address", back_populates="user")
class Address(Base):
    __tablename__ = ‘address‘
    id = Column(Integer, primary_key=True)
    email = Column(String)
    user_id = Column(Integer, ForeignKey(‘user.id‘))
    user = relationship("User", back_populates="addresses")

Above, we add a .user relationship to Address explicitly. On both relationships, the back_populates directive tells each relationship about the other one, indicating that they should establish “bidirectional” behavior between each other. The primary effect of this configuration is that the relationship adds event handlers to both attributes which have the behavior of “when an append or set event occurs here, set ourselves onto the incoming attribute using this particular attribute name”. The behavior is illustrated as follows. Start with a User and an Address instance. The .addresses collection is empty, and the .user attribute is None:

下面来看下backref相关的源码

def backref(name, **kwargs):
    """Create a back reference with explicit keyword arguments, which are     the same arguments one can send to :func:`relationship`.

    Used with the ``backref`` keyword argument to :func:`relationship` in
    place of a string argument, e.g.::

        ‘items‘:relationship(
            SomeItem, backref=backref(‘parent‘, lazy=‘subquery‘))

    .. seealso::

        :ref:`relationships_backref`

    """

    return (name, kwargs)
param backref:
          indicates the string name of a property to be placed on the related
          mapper‘s class that will handle this relationship in the other
          direction. The other property will be created automatically
          when the mappers are configured.  Can also be passed as a
          :func:`.backref` object to control the configuration of the
          new relationship.
时间: 2024-10-12 13:06:02

SQLAlchemy_定义(一对一/一对多/多对多)关系的相关文章

PD 15.1 安装 破解 , 简单使用 (一对多,多对多关系生成sql脚本)

  1:运行  PowerDesigner15_Evaluation.exe 默认   2: 安装完毕后,不要执行,下面我们进行 破解 把 PowerDesigner15汉化+注册补丁  下的所有文件,覆盖 PD的安装目录下的文件 然后我们打开 PD,点击 帮助 –> About  看到下面窗口中红色方框,就表示已经破解 + 汉化成功 PD 15.1 安装 破解 , 简单使用 (一对多,多对多关系生成sql脚本)

mybatis 一对一 一对多 多对多

一对一 一对多 多对多 原文地址:https://www.cnblogs.com/cwone/p/11909271.html

表关系(一对一,一对多,多对多)

可以在数据库图表中的表之间创建关系,以显示一个表中的列与另一个表中的列是如何相链接的. 在一个关系型数据库中,利用关系可以避免多余的数据.例如,如果设计一个可以跟踪图书信息的数据库,您需要创建一个名为 titles 的表,它用来存储有关每本书的信息,例如书名.出版日期和出版社.您也可能保存有关出版社的信息,诸如出版社的电话.地址和邮政编码.如果您打算在 titles 表中保存所有这些信息,那么对于某出版社出版的每本书都会重复该出版社的电话号码. 更好的方法是将有关出版社的信息在单独的表,publ

django mysql 表的一对一 一对多 多对多

表结构的设计 一对一 多对一  将key写在多 多对多 外键: 描述  多对一的关系 写在多的一方 class Book(models.Model) title = models.CharField(max_length=32,unique=Ture) publisher = models.ForeignKey (to=Publisher,on_deleete=models.CASADE) publisher = models.ForeignKey(to='Publisher', on_dele

Hibernate 映射文件的配置 核心文件的配置 一对一 一对多 多对多 hibernate实现分页 Hibernate中session的关闭问题总结

以留言系统为实例 1 .配置映射文件:首先得引入约束dtd <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 然后<hibernate-mapping></hibernate-mapping>映射标签 <

Flask 数据库多对多关系

数据库使用关系建立记录之间的联系.其中,一对多关系是最常用的关系类型,它把一个记录和一组相关的记录联系在一起.实现这种关系时,要在"多"这一侧加入一个外键,指向"一"这一侧联接的记录.大部分的其他关系类型都可以从一对多类型中衍生. 多对一关系从"多"这一侧看,就是一对多关系. 一对一关系类型是简化版的一对多关系, 限制"多"这一侧最多只能有一个记录.唯一不能从一对多关系中简单演化出来的类型是多对多关系,这种关系的两侧都有多个记

关联映射 ---- Hibernate之多对多关系

叙:上一章详细的记录了关联映射中的"一对多|多对一"关系.级联操作.关系的维护等知识点,本章节轻风学习记录的是级联关系中的"多对多"关系: Hibernate的"多对多"级联关系 1. 介绍 在生活中很多关系都是多对多的,比如一个人在公司是技术部的同时也是营销部的(只是个例子),所以,多对对关系是很普遍的,一个对象有多个角色,而一个角色又可以有多个对象,因此最正确的做法是在对象与角色之间创建一个新的表,用来保存对象和角色的主键,方便调用查看相应的

jango 模型管理数据model,数据库外键主键与一对一,一对多,多对多关系

四.models.py 定义和管理模型: 4.1模型class的属性就映射与数据库的字段参数 继承models.Model class TestClass(models.Model): 4.2在数据库生成数据表: #django默认在makemigrations会为表对象创建主键id,id = models.AutoField(primary_key=True) 你也可以自定义一个主键对象: 4.2.1: 生成迁移文件python manage.py makemigrations 4.2.2执行

总结一下数据库的 一对多、多对一、一对一、多对多 关系

关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系: 一对多:从球队角度来说一个球队拥有多个球员 即为一对多 多对一:从球员角度来说多个球员属于一个球队 即为多对一 数据表间一对多关系如下图: 关联映射:一对一 一对一关系就如球队与球队所在地址之间的关系,一支球队仅有一个地址,而一个地址区也仅有一支球队. 数据表间一对一关系的表现有两种,一种是外键关联,一种是主键关联.图示如下: 一对一外键关联: 一对一主键关联:要求两个表的主键必须完全一致,通过两个表的主键建立关联关