2015-10-26 4 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) 

После нового объекта совершали, я запрашивая его.

>>> 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_lineup и m.team2_lineup являются одинаковыми. Как я могу это решить? Кроме того, как мне назначить идентификатор для каждой линейки (в списках с одинаковыми игроками должен быть одинаковый идентификатор)?

ответ

1

Мне удалось решить мою проблему. Мне пришлось добавлять идентификаторы в список (который я переименовал в Team) и указать, как присоединиться к таблицам, предоставив два разных идентификатора для этих команд. Еще одно решение пути, отправленное Андре.

Вот код:

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 (два) Дифференц выстраиваются в линию, когда вы используете тот же матч идентификатор для двух разных составов происходит ошибка этого запроса, чтобы вернуть список;
  • Я плохо разбираюсь в спорте, но я думаю, что вы можете улучшить нормализацию моделей. Например: Создать новую модель Team

Мое предложение изменить некоторые модели для многие ко многим, как это:

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» для каждого матча. Я не знаю, возможно ли в спорте, которым вы управляете.

Смежные вопросы