我有一个Player
课程,每个玩家拥有X个Character
个实例:
class Player(Model):
characters = relationship('Character', back_populates='owner')
class Character(Model):
owner = relationship('Player', back_populates='characters')
owner_id = Column('player_id', Integer, ForeignKey('player.id'))
但现在我想将这些字符拆分为两个单独的列表,即graveyard
和普通characters
列表中的列表:
class Player(Model):
characters = relationship('Character', back_populates='owner')
graveyard = relationship('Character', back_populates='owner')
class Character(Model):
owner = relationship('Player', back_populates='characters')
owner_id = Column('player_id', Integer, ForeignKey('player.id'))
但正如您所看到的,SQLAlchemy无法区分这两个列表。我该如何启用此类行为?
答案 0 :(得分:2)
我大胆地假设有一种方法可以区分角色是否在坟墓场中。否则这没有任何意义。如果"字符" table包含有关角色位置的信息,那么你需要的是" alternate join"如下所述:http://docs.sqlalchemy.org/en/latest/orm/join_conditions.html#specifying-alternate-join-conditions
这是一个愚蠢但有效的例子(忽略了gobbledygook与会话等,我只是在一段旧代码上复制了一个新模型)如果我理解你的问题是正确的。它将创建一个模型,插入一个玩家,一个活着的角色和一个死角色,然后显示它们。这是你在找什么?
from sqlalchemy import Integer, ForeignKey, String, Column, Boolean, create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import relationship
Base = declarative_base()
engine = create_engine("postgresql://test:test@localhost/test", echo=False)
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
class Player(Base):
__tablename__ = 'player'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
characters = relationship('Character', primaryjoin="and_(Character.player_id == Player.id, \
Character.alive == True)")
graveyard = relationship('Character', primaryjoin="and_(Character.player_id == Player.id, \
Character.alive == False)")
class Character(Base):
__tablename__ = 'character'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
alive = Column(Boolean)
player_id = Column(Integer, ForeignKey('player.id'))
Base.metadata.create_all(engine)
try:
p = Player(name="foo")
Session.add(p)
Session.commit()
except IntegrityError:
Session.rollback()
try:
p = Session.query(Player).filter(Player.name == "foo").one()
c1 = Character(name="c1", alive=True, player_id=p.id)
c2 = Character(name="c2", alive=False, player_id=p.id)
Session.add(c1)
Session.add(c2)
Session.commit()
except IntegrityError:
Session.rollback()
player = Session.query(Player).filter(Player.name == "foo").one()
print player
for c in player.characters:
print c.name
for c in player.graveyard:
print c.name