下面涉及到的代码中,均导入了如下类或属性
from sqlalchemy import Table,Column,Integer,ForeignKey
from sqlalchemy.orm import relationship,backref
from sqlalchemy.ext.declarative import declarative_base
Base=declarative_base() #该类的子类可以自动与一个表关联。
一对多关系:
设Parent类为“一”部分,Child类为“多”部分。有如下代码:
class Parent(Base): __tablename__='parent' #自动与数据库中的表parent关联 id=Column(Integer,primary_key=True) children=relationship("Child") class Child(Base): __tablename__='child' id=Column(Integer,primary_key=True) parent_id=Column(Integer,ForeignKey('parent.id'))
在“多”的部分设置relationship();在“一”部分设置外键。
sqlalchemy.orm.relationship(argument, secondary=None, primaryjoin=None, secondaryjoin=None, foreign_keys=None, uselist=None, order_by=False, backref=None, back_populates=None, post_update=False, cascade=False, extension=None, viewonly=False, lazy=True, collection_class=None, passive_deletes=False, passive_updates=True, remote_side=None, enable_typechecks=True, join_depth=None, comparator_factory=None, single_parent=False, innerjoin=False, distinct_target_key=None, doc=None, active_history=False, cascade_backrefs=True, load_on_pending=False, strategy_class=None, _local_remote_pairs=None, query_class=None, info=None)
为了建立双向连接,在relationship()中设置backref。
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'))
此时,child就可以获取parent的属性了。如child.parent.id。backref是反向引用,在Child类上声明新的属性parent。
多对一:
与一对多相反,参考上述一对多
一对一:
一对一可参考上述一对多进行转化,需设置relationship()中的uselist为False:
class Parent(Base): __tablename__='parent' id=Column(Integer,primary_key=True) child=relationship("Child",uselist=False,backref="parent") class Child(Base): __tablename__='child' id=Column(Integer,primary_key=True) parent_id=Column(Integer,ForeignKey('parent.id'))
多对多:
为了表示多对多的关系,需要引入一个关系表,对于这个关系表,强烈建议不使用模型,而是采用一个实际的表。
需要引入Table类,并且在relationship()中设置secondary选项。关系表中的列为另两个表的主键。Table类通常使用MetaData来关联declarative base类。
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="parent") class Child(Base): __tablename__='right' id=Column(Integer,primary_key=True)
为了建立双向关系,加入backref关键字:
ssociation_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) class Child(Base): __tablename__='right' id=Column(Integer,primary_key=True)
secondary也可以接受以下两种形式:
1、The secondary argument of relationship() also accepts a callable that returns the ultimate argument, which is evaluated only when mappers are first used。如secondary=lambda:association_table
2、string name of the table:secondary="association"
从多对多表中删除一行:
形如:myparent.children.remove(somechild)删除记录,那么相应的行会自动在“secondary” table中删除,无需人工删除。
但像session.delete(somechild)这样删除记录,相应的在“secondary” table中的记录则分情况讨论:
1、如果从parent到child存在关系,但从child到parent没有关系(关系不是双向的),那么在“secondary” table中不会被删除。
2、如果关系是双向的,那么在“secondary” table中会自动删除。
3、如果数据库支持 ON DELETE CASCADE(级联删除),那么数据会从“secondary” table中删除。
关联对象:
对于多对多关系,Tabel表中列包含两个外键。当该表包含其他信息时,可使用Association类。从Parent到Association是一对多;从Association到Child是多对一。
class Association(Base): __tablename__='asscociation' left_id=Column(Integer,ForeignKey('left.id'),primary_key=True) right_id=Column(Integer,ForeignKey('right.id'),primary_key=True) extra_data=Column(String(50)) #额外信息 child=relationship("Child") class Parent(Base): __tablename__='left' id=Column(Integer,primary_key=True) children=relationship('Association') class Child(Base): __tablename__='right' id=Column(Integer,primary_key=True)
建立双向关系的话,在relationship中增加backref属性。
class Association(Base): __tablename__ = 'association' left_id = Column(Integer, ForeignKey('left.id'), primary_key=True) right_id = Column(Integer, ForeignKey('right.id'), primary_key=True) extra_data = Column(String(50)) child = relationship("Child", backref="parent_assocs") class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Association", backref="parent") class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True)
采用以上association 模式,在添加数据时,首先将Child实例与Association绑定,然后再将child添加到parent中。
p=Parent()
a=Association(extra_data="some data")
a.child=Child()
p.children.append(a)
在遍历child对象及association的属性时,通过association进行访问:
for assoc in p.children:
print assoc.extra_data
print assoc.child
原文:http://docs.sqlalchemy.org/en/rel_0_9/orm/basic_relationships.html