2015-10-26 62 views
0

我宣布以下型号:SQLAlchemy的关系,同桌

from sqlalchemy import (
    Column, 
    Table, 
    Integer, 
    Date, 
    String, 
    ForeignKey, 
) 

from sqlalchemy import create_engine 

from sqlalchemy.orm import sessionmaker 

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.ext.associationproxy import association_proxy 

from sqlalchemy.orm import relationship, backref 

engine = create_engine('sqlite:///data.sqlite') 
DBSession = sessionmaker(bind=engine) 

Base = declarative_base() 


lineup = Table('lineups', Base.metadata, 
       Column('match_id', Integer, ForeignKey('data.id')), 
       Column('player_id', Integer, ForeignKey('players.id'))) 


class Match(Base): 
    __tablename__ = 'data' 

    id = Column(Integer, primary_key=True) 
    date = Column(Date) 
    tournament = Column(String) 
    team1 = Column(String) 
    team2 = Column(String) 
    team1_lineup = relationship('Player', secondary=lineup) 
    team2_lineup = relationship('Player', secondary=lineup) 
    best_of = Column(Integer) 
    maps = relationship('Map') 
    score = Column(String) 


class Map(Base): 
    __tablename__ = 'maps' 

    id = Column(Integer, primary_key=True) 
    match = Column(Integer, ForeignKey('data.id')) 
    name = Column(String) 
    score = Column(String) 


class Player(Base): 
    __tablename__ = 'players' 

    id = Column(Integer, primary_key=True) 
    nickname = Column(String) 
    team = Column(String) 

而且我创造新的Match对象是这样的:

match = Match(...) # all kwargs except team1_lineup and team2_lineup 

p1 = Player(id=1, nickname='p1', team='team') 
p2 = Player(id=2, nickname='p2', team='team') 
p3 = Player(id=3, nickname='p2', team='team') 

match.team1_lineup.append(p1) 
match.team2_lineup.append(p2) 
match.team2_lineup.append(p3) 

commiting新对象后,我查询了。

>>> from hltv.models import Match, DBSession 
>>> s = DBSession() 
>>> m = s.query(Match).first() 
>>> m.team1_lineup 
[<hltv.models.Player object at 0x7f1a93009d10>, <hltv.models.Player object at 0x7f1a93009d90>, <hltv.models.Player object at 0x7f1a93009e10>] 
>>> m.team2_lineup 
[<hltv.models.Player object at 0x7f1a93009d10>, <hltv.models.Player object at 0x7f1a93009d90>, <hltv.models.Player object at 0x7f1a93009e10>] 

问题是m.team1_lineupm.team2_lineup是相同的。我该如何解决这个问题? 另外,如何为每个阵容分配ID(具有相同球员的阵容应该有相同的ID)?

回答

1

我设法解决了我的问题。我不得不将ID添加到阵容中(我已将其重命名为Team),并通过为这些球队提供两个不同的ID来指定如何连接表。 André发布的另一种解决方案。

下面是代码:

from sqlalchemy import (
    Column, 
    Table, 
    Integer, 
    Date, 
    String, 
    ForeignKey, 
) 

from sqlalchemy import create_engine 

from sqlalchemy.orm import sessionmaker 

from sqlalchemy.ext.declarative import declarative_base 

from sqlalchemy.orm import relationship, backref 

engine = create_engine('sqlite:///data.sqlite') 
DBSession = sessionmaker(bind=engine) 

Base = declarative_base() 


class Match(Base): 
    __tablename__ = 'data' 

    id = Column(Integer, primary_key=True) 
    date = Column(Date) 
    tournament = Column(String) 
    best_of = Column(Integer) 
    score = Column(String) 
    maps = relationship('Map') 
    team1_id = Column(ForeignKey('team.id')) 
    team2_id = Column(ForeignKey('team.id')) 

    team1 = relationship('Team', primaryjoin='Match.team1_id == Team.id') 
    team2 = relationship('Team', primaryjoin='Match.team2_id == Team.id') 


class Map(Base): 
    __tablename__ = 'map' 

    id = Column(Integer, primary_key=True) 
    match = Column(Integer, ForeignKey('data.id')) 
    name = Column(String) 
    score = Column(String) 


lineup = Table('lineup', 
       Base.metadata, 
       Column('player_id', Integer, ForeignKey('player.id')), 
       Column('team_id', Integer, ForeignKey('team.id'))) 



class Player(Base): 
    __tablename__ = 'player' 

    id = Column(Integer, primary_key=True) 
    nickname = Column(String) 


class Team(Base): 
    __tablename__ = 'team' 

    id = Column(Integer, primary_key=True) 
    name = Column(String) 

    players = relationship('Player', secondary=lineup, backref='teams') 
+0

我很高兴在最后的解决方案,帮助。不要忘记设置你自己的答案解决。 –

0

我有一些建议,关系:

  • 考虑到你对每场比赛2(二)队和2(二)型动物排队,当您使用同一场比赛中ID为两个不同的阵容发生这个查询错误返回阵容;
  • 我不擅长运动,但我认为你可以在模型上做更好的标准化。例如:创建一个新的模特队

我的建议是改变一些模型多对多,这样的:

from sqlalchemy import (
    Column, 
    Table, 
    Integer, 
    Date, 
    String, 
    ForeignKey, 
) 

from sqlalchemy import create_engine 

from sqlalchemy.orm import sessionmaker 

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.ext.associationproxy import association_proxy 

from sqlalchemy.orm import relationship, backref 

engine = create_engine('sqlite:///data.sqlite') 
DBSession = sessionmaker(bind=engine) 

Base = declarative_base() 

lineup = Table('lineups', Base.metadata, 
       Column('team_id', Integer, ForeignKey('teams.id')), 
       Column('player_id', Integer, ForeignKey('players.id'))) 

class Team(Base): 
    __tablename__ = 'teams' 
    id = Column(Integer, primary_key=True,autoincrement= True) 
    name = Column(String) 
    team_lineup = relationship('Player',secondary=lineup) 

match_team = Table('match_teams', Base.metadata, 
       Column('match_id', Integer, ForeignKey('matches.id')), 
       Column('team_id', Integer, ForeignKey('teams.id'))) 

class Match(Base): 
    __tablename__ = 'matches' 
    id = Column(Integer, primary_key=True,autoincrement= True) 
    date = Column(Date) 
    tournament = Column(String) 
    team = relationship('Team',secondary=match_team) 
    best_of = Column(Integer) 
    maps = relationship('Map') 
    score = Column(String) 

class Map(Base): 
    __tablename__ = 'maps' 
    id = Column(Integer, primary_key=True,autoincrement= True) 
    match = Column(Integer, ForeignKey('matches.id')) 
    name = Column(String) 
    score = Column(String) 

class Player(Base): 
    __tablename__ = 'players' 
    id = Column(Integer, primary_key=True,autoincrement= True) 
    nickname = Column(String) 

创建OBJETS ...

s = DBSession() 

Base.metadata.drop_all(engine) 
Base.metadata.create_all(engine) 

t1 = Team(name="t1") 
t2 = Team(name="t2") 

p1 = Player() 
p2 = Player() 
p3 = Player() 

s.add(p1) 
s.add(p2) 
s.add(p3) 

t1.team_lineup.append(p1) 
t2.team_lineup.append(p2) 
t2.team_lineup.append(p3) 

s.add(t1) 
s.add(t2) 

m = Match() 
m.tournament="xpto" 
m.team.append(t1) 
m.team.append(t2) 

s.add(m) 
s.commit() 

而且之后,您可以看到阵容与您的期望类似:

>>> m = s.query(Match).first() 
>>> for t in m.team: 
...  print t.team_lineup 
... 
[<__main__.Player object at 0x10b57c890>] 
[<__main__.Player object at 0x10b57c910>, <__main__.Player object at 0x10b57c990>] 

在这种情况下,您可以为每场比赛设置“n”个参赛队。我不知道你在管理的运动中是否有可能。