SQLALCHEMY中的基本关系模式

下面涉及到的代码中,均导入了如下类或属性

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

你可能感兴趣的:(SQLALCHEMY中的基本关系模式)