2015-10-26 70 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」個參賽隊。我不知道你在管理的運動中是否有可能。