我有三个相关的实体如下:
这些是我的模特:
def ReferenceCol(tablename, nullable=False, pk_name='id', **kwargs):
"""Column that adds primary key foreign key reference.
Usage: ::
category_id = ReferenceCol('category')
category = relationship('Category', backref='categories')
"""
return db.Column(
db.ForeignKey("{0}.{1}".format(tablename, pk_name)),
nullable=nullable, **kwargs)
class Player(Model):
__tablename__ = 'players'
id = Column(db.Integer, primary_key=True)
player_name = Column(db.String(80), unique=False, nullable=False)
alliance_id = ReferenceCol('alliances', nullable=True)
...
def __repr__(self):
return '<Player({player_name!r})>'.format(player_name=self.player_name)
class Alliance(Model):
__tablename__ = 'alliances'
id = Column(db.Integer, primary_key=True)
alliance_name = Column(db.String(80), unique=False, nullable=False)
...
def __repr__(self):
return '<Alliance({alliance_name!r})>'.format(alliance_name=self.alliance_name)
class Habitat(Model):
__tablename__ = 'habitats'
id = Column(db.Integer, primary_key=True)
castle_name = Column(db.String(80), unique=False, nullable=True)
player_id = ReferenceCol('players', nullable=True)
...
def __repr__(self):
return '<Habitat({castle_name!r})>'.format(castle_name=self.castle_name)
我可以轻松加入habiats和玩家:
# Join habitats and players
for habitat, player in db.session.query(Habitat, Player).join(Player).all()[:3]:
print habitat, player
球员和联盟:
# Join players and alliances
for player, alliance in db.session.query(Player, Alliance).join(Alliance).all()[:3]:
print player, alliance
但如何加入所有三个表?我怎样才能加入栖息地,球员和联盟?我正在寻找可以做的事情:
for castle, player, alliance in magic_join():
print castle, player, alliance
答案 0 :(得分:4)
您可以将多个模型传递给join。订单很重要:如果您查询Habitat
,您只会获得与玩家有栖息地和联盟的玩家。如果您使用外部联接查询Alliance
,那么您将获得与其玩家及其栖息地的所有联盟。
for a, p, h in session.query(Alliance, Player, Habitat).outerjoin(Player, Habitat):
print(a.id, p.id, h.id)
不是查询多个对象,而是定义relationships。查询Alliance
并使用eager loading加载关系而无需额外查询。迭代联盟,并为每个联盟迭代其玩家等等。
class Alliance(Base):
__tablename__ = 'alliance'
id = sa.Column(sa.Integer, primary_key=True)
class Player(Base):
__tablename__ = 'player'
id = sa.Column(sa.Integer, primary_key=True)
alliance_id = sa.Column(sa.ForeignKey(Alliance.id), nullable=False)
alliance = orm.relationship(Alliance, backref='players')
class Habitat(Base):
__tablename__ = 'habitat'
id = sa.Column(sa.Integer, primary_key=True)
player_id = sa.Column(sa.ForeignKey(Player.id), nullable=False)
player = orm.relationship(Player, backref='habitats')
for a in session.query(Alliance).options(
db.joinedload(Alliance.players).joinedload(Player.habitats)
):
for p in a.players:
for h in p.habitats:
print(a.id, p.id, h.id)