与同一个表

时间:2015-10-26 20:47:01

标签: python sqlite orm 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)

提交新对象后,我查询它。

>>> 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)?

2 个答案:

答案 0 :(得分:2)

我设法解决了我的问题。我必须在阵容中添加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')

答案 1 :(得分:0)

我在关系中有一些建议:

  • 考虑到每场比赛2(2)队和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>]

在这种情况下,您可以拥有&#34; n&#34;每场比赛的球队。我不知道你所管理的运动是否有可能。