flask-sqlalchemy中一对多,一对一,多对多模型

Basic Relationship Patterns

基本关系模式 

下列的 import 语句,应用到接下来所有的代章节中:

1 from sqlalchemy import Table, Column, Integer, ForeignKey
2 from sqlalchemy.orm import relationship
3 from sqlalchemy.ext.declarative import declarative_base
4 
5 Base = declarative_base()

One To Many

表示一对多的关系时,在子表类中通过 foreign key (外键)引用父表类。 

然后,在父表类中通过 relationship() 方法来引用子表的类:

 1 class Parent(Base):
 2     __tablename__ = 'parent'
 3     id = Column(Integer, primary_key=True)
 4     children = relationship("Child")
 5    # 在父表类中通过 relationship() 方法来引用子表的类集合
 6 
 7 class Child(Base):
 8     __tablename__ = 'child'
 9     id = Column(Integer, primary_key=True)
10     parent_id = Column(Integer, ForeignKey('parent.id')) 11 # 在子表类中通过 foreign key (外键)引用父表的参考字段

在一对多得关系中建立双向的关系,这样的话在对方看来这就是一个多对一的关系,

在子表类中附加一个 relationship() 方法,并且在双方的 relationship() 方法中使用 relationship.back_populates 方法参数:

 1 class Parent(Base):
 2     __tablename__ = 'parent'
 3     id = Column(Integer, primary_key=True)
 4     children = relationship("Child", back_populates="parent")
 5 
 6 class Child(Base):
 7     __tablename__ = 'child'
 8     id = Column(Integer, primary_key=True)
 9     parent_id = Column(Integer, ForeignKey('parent.id')) 10 parent = relationship("Parent", back_populates="children") 11 # 子表类中附加一个 relationship() 方法 12 # 并且在(父)子表类的 relationship() 方法中使用 relationship.back_populates 参数

这样的话子表将会在多对一的关系中获得父表的属性

或者,可以在单一的 relationship() 方法中使用 backref 参数来代替 back_populates 参数:

1 class Parent(Base):
2     __tablename__ = 'parent'
3     id = Column(Integer, primary_key=True)
4     children = relationship("Child", backref="parent")
5 
6 class Child(Base):
7     __tablename__ = 'child'
8     id = Column(Integer, primary_key=True)
9     parent_id = Column(Integer, ForeignKey('parent.id'))

One To One

一对一是两张表之间本质上的双向关系。

要做到这一点,只需要在一对多关系基础上的父表中使用uselist参数来表示。

把一对多转化成一对一:

 1 class Parent(Base):
 2     __tablename__ = 'parent'
 3     id = Column(Integer, primary_key=True)
 4     child = relationship("Child", uselist=False, back_populates="parent")
 5 
 6 class Child(Base):
 7     __tablename__ = 'child'
 8     id = Column(Integer, primary_key=True)
 9     parent_id = Column(Integer, ForeignKey('parent.id')) 10 parent = relationship("Parent", back_populates="child")

把多对一转化成一对一:

 1 class Parent(Base):
 2     __tablename__ = 'parent'
 3     id = Column(Integer, primary_key=True)
 4     child_id = Column(Integer, ForeignKey('child.id'))
 5     child = relationship("Child", back_populates="parent")
 6 
 7 class Child(Base):
 8     __tablename__ = 'child'
 9     id = Column(Integer, primary_key=True) 10 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: 
同样的,可以使用下面这种方式:

 1 from sqlalchemy.orm import backref
 2 
 3 class Parent(Base):
 4     __tablename__ = 'parent'
 5     id = Column(Integer, primary_key=True)
 6     child_id = Column(Integer, ForeignKey('child.id'))
 7     child = relationship("Child", backref=backref("parent", uselist=False))
 8 
 9 class Child(Base): 10 __tablename__ = 'child' 11 id = Column(Integer, primary_key=True) 12 parent_id = Column(Integer, ForeignKey('parent.id'))

Many To Many

多对多关系会在两个类之间增加一个关联的表。 

这个关联的表在 relationship() 方法中通过 secondary 参数来表示。 

通常的,这个表会通过 MetaData 对象来与声明基类关联, 

所以这个 ForeignKey 指令会使用链接来定位到远程的表:

多对多关系中的两个表之间的一个关联表

 
 1 association_table = Table('association', Base.metadata,
 2     Column('left_id', Integer, ForeignKey('left.id')),
 3     Column('right_id', Integer, ForeignKey('right.id'))
 4 )
 5 
 6 class Parent(Base):
 7     __tablename__ = 'left'
 8     id = Column(Integer, primary_key=True) 9 children = relationship("Child", 10 secondary=association_table) 11 # 在父表中的 relationship() 方法传入 secondary 参数,其值为关联表的表名 12 13 class Child(Base): 14 __tablename__ = 'right' 15 id = Column(Integer, primary_key=True)

双向关系中,两个表类都会包含这个集合。 

指定使用 relationship.back_populates 参数,并且为每一个 relationship() 方法指定共用的关联表:

 1  association_table = Table('association', Base.metadata,
 2     Column('left_id', Integer, ForeignKey('left.id')),
 3     Column('right_id', Integer, ForeignKey('right.id'))
 4 )
 5 
 6 class Parent(Base):
 7     __tablename__ = 'left'
 8     id = Column(Integer, primary_key=True) 9 children = relationship( 10 "Child", 11 secondary=association_table, 12 back_populates="parents") 13 14 class Child(Base): 15 __tablename__ = 'right' 16 id = Column(Integer, primary_key=True) 17 parents = relationship( 18 "Parent", 19 secondary=association_table, 20 back_populates="children")

当在父表类的 relationship() 方法中使用 backref参数代替 relationship.back_populates 时,backref 会自动的为子表类加载同样的 secondary 参数。

 1 association_table = Table('association', Base.metadata,
 2     Column('left_id', Integer, ForeignKey('left.id')),
 3     Column('right_id', Integer, ForeignKey('right.id'))
 4 )
 5 
 6 class Parent(Base):
 7     __tablename__ = 'left'
 8     id = Column(Integer, primary_key=True) 9 children = relationship("Child", 10 secondary=association_table, 11 backref="parents") 12 13 class Child(Base): 14 __tablename__ = 'right' 15 id = Column(Integer, primary_key=True)

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:

1 class Parent(Base):
2     __tablename__ = 'left'
3     id = Column(Integer, primary_key=True)
4     children = relationship("Child",
5                     secondary=lambda: association_table,
6                     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:

1 class Parent(Base):
2     __tablename__ = 'left'
3     id = Column(Integer, primary_key=True)
4     children = relationship("Child",
5                     secondary="association",
6                     backref="parents")

猜你喜欢

转载自www.cnblogs.com/notzy/p/9187232.html
今日推荐