一:一对多
表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类,然后,在父表类中通过 relationship() 方法来引用子表的类。
在一对多的关系中建立双向的关系,这样的话在对方看来这就是一个多对一的关系,在子表类中附加一个 relationship() 方法,并且在双方的 relationship() 方法中使用 relationship.back_populates 方法参数。这样的话子表将会在多对一的关系中获得父表的属性,或者,可以在单一的 relationship() 方法中使用 backref 参数来代替 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.parent
是指一个Parent实例,另一方面,
Parent
.
children 是指的一个Child
实例列表。
# -*- coding:utf-8 -*- __author__ = 'shisanjun' import sqlalchemy from sqlalchemy import Column,Integer,String,ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker,relationship #创建连接 engine=sqlalchemy.create_engine("mysql+pymysql://admin:admin@192.168.0.121/test2?charset=utf8",echo=True) #声明ORM映射基类 BASE=declarative_base() class User(BASE): __tablename__="users" #指定表名 id=Column(Integer,primary_key=True) #建立主键 name=Column(String(32)) fullname=Column(String(32)) password=Column(String(32)) def __repr__(self): #返回对象时打印显示 return "name:%s full name:%s password:%s" %(self.name,self.fullname,self.password) class Address(BASE): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email_address = Column(String, nullable=False) user_id = Column(Integer, ForeignKey('users.id')) user = relationship("User", back_populates="addresses") def __repr__(self): return "<Address(email_address='%s')>" % self.email_address BASE.metadata.create_all(engine) Session=sessionmaker(bind=engine) #实例化会话类 session=Session() jack=User(name='jack',fullname='Jack Bean',password='gjffdd') jack.addresses = [ Address(email_address='jack@google.com'), Address(email_address='j25@yahoo.com')] session.add(jack) session.commit() jack = session.query(User).filter_by(name='jack').one() print(jack.addresses)
二:一对一
一对一是两张表之间本质上的双向关系。 要做到这一点,只需要在一对多关系基础上的父表中使用 uselist 参数来表示。
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")
三:多对多
多对多关系会在两个类之间增加一个关联的表。
这个关联的表在 relationship() 方法中通过 secondary 参数来表示
通常的,这个表会通过 MetaData 对象来与声明基类关联
所以这个 ForeignKey 指令会使用链接来定位到远程的表
双向关系中,两个表类都会包含这个集合。
指定使用 relationship.back_populates 参数,并且为每一个 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)