'Table' object has no attribute 'id' on SQLAlchemy relation The Next CEO of Stack OverflowHow to sort a list of objects based on an attribute of the objects?How to know if an object has an attribute in PythonDetermine the type of an object?Formalchemy - form for one to many relationHow to force aliases for columns in SQLAlchemy?Getting warning when 2 models inherit the same object in flask-sqlalchemyPython: sqlalchemy the result of schema isn't expectedHow to initialize the object (table) using dict with some relationship with other table via sqlalchemy?SQLAlchemy “AttributeError: 'str' object has no attribute 'c'”How to count child table items with or without join to parent table using SQLAlchemy?

How does the Z80 determine which peripheral sent an interrupt?

Grabbing quick drinks

How do I reset passwords on multiple websites easily?

If the heap is zero-initialized for security, then why is the stack merely uninitialized?

Written every which way

How did people program for Consoles with multiple CPUs?

Why does standard notation not preserve intervals (visually)

Novel about a guy who is possessed by the divine essence and the world ends?

Is it professional to write unrelated content in an almost-empty email?

Is there a difference between "Fahrstuhl" and "Aufzug"

Preparing Indesign booklet with .psd graphics for print

Does it take more energy to get to Venus or to Mars?

Would a galaxy be visible from outside, but nearby?

Inappropriate reference requests from Journal reviewers

What can we do to stop prior company from asking us questions?

Are there any unintended negative consequences to allowing PCs to gain multiple levels at once in a short milestone-XP game?

How do scammers retract money, while you can’t?

Which tube will fit a -(700 x 25c) wheel?

Real integral using residue theorem - why doesn't this work?

How does the mv command work with external drives?

Complex fractions

Anatomically Correct Strange Women In Ponds Distributing Swords

What does convergence in distribution "in the Gromov–Hausdorff" sense mean?

Multiple labels for a single equation



'Table' object has no attribute 'id' on SQLAlchemy relation



The Next CEO of Stack OverflowHow to sort a list of objects based on an attribute of the objects?How to know if an object has an attribute in PythonDetermine the type of an object?Formalchemy - form for one to many relationHow to force aliases for columns in SQLAlchemy?Getting warning when 2 models inherit the same object in flask-sqlalchemyPython: sqlalchemy the result of schema isn't expectedHow to initialize the object (table) using dict with some relationship with other table via sqlalchemy?SQLAlchemy “AttributeError: 'str' object has no attribute 'c'”How to count child table items with or without join to parent table using SQLAlchemy?










1















I've got a relationship set up across three separate classes using SQLAlchemy, with an association table for a many-to-many relationship. Minimal example:



from sqlalchemy import * 
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import configure_mappers, relationship

Base = declarative_base()

teams_users = Table(
'teams_users', Base.metadata,
Column('team_id', ForeignKey('teams.id')),
Column('user_id', ForeignKey('users.id'))
)

class User(Base):
__tablename__ = 'users'
# No autoincrement, since we're using externally-generated UIDs
id = Column(Integer, primary_key=True, autoincrement=False)
teams = relationship('Team', secondary=teams_users, back_populates="users")

class Team(Base):
__tablename__ = 'teams'
id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
game_id = Column(Integer, ForeignKey('games.id'), nullable=False)
games = relationship("Game", foreign_keys='games.id')
users = relationship("User", secondary='teams_users', back_populates="teams")

class Game(Base):
__tablename__ = 'games'
id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
team1_id = Column(Integer, ForeignKey('teams.id'))
team2_id = Column(Integer, ForeignKey('teams.id'))
team1 = relationship("Team", back_populates="games", foreign_keys=team1_id, uselist=False)
tean2 = relationship("Team", back_populates="games", foreign_keys=team2_id, uselist=False)

# done declaring, trigger the error
configure_mappers()


Attempting to query any of these relations returns a 'Table' object has no attribute 'id' error:



Traceback (most recent call last):
File "...", line 35, in <module>
configure_mappers()
File "/.../sqlalchemy/orm/mapper.py", line 3033, in configure_mappers
mapper._post_configure_properties()
File "/.../sqlalchemy/orm/mapper.py", line 1832, in _post_configure_properties
prop.init()
File "/.../sqlalchemy/orm/interfaces.py", line 183, in init
self.do_init()
File "/.../sqlalchemy/orm/relationships.py", line 1655, in do_init
self._process_dependent_arguments()
File "/.../sqlalchemy/orm/relationships.py", line 1680, in _process_dependent_arguments
setattr(self, attr, attr_value())
File "/.../sqlalchemy/ext/declarative/clsregistry.py", line 281, in __call__
x = eval(self.arg, globals(), self._dict)
File "<string>", line 1, in <module>
AttributeError: 'Table' object has no attribute 'id'


My goal in constructing it this way is that I could easily check which Teams each User has ever been a part of.



Additionally, Game has two foreign keys into Team because the use case for this project supports arbitrarily sized teams, but only ever two teams. This allows me to have a result of "team1 won" and immediately have a reference to the winning users for stat tracking and historical reference.



What am I doing wrong here?










share|improve this question




























    1















    I've got a relationship set up across three separate classes using SQLAlchemy, with an association table for a many-to-many relationship. Minimal example:



    from sqlalchemy import * 
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import configure_mappers, relationship

    Base = declarative_base()

    teams_users = Table(
    'teams_users', Base.metadata,
    Column('team_id', ForeignKey('teams.id')),
    Column('user_id', ForeignKey('users.id'))
    )

    class User(Base):
    __tablename__ = 'users'
    # No autoincrement, since we're using externally-generated UIDs
    id = Column(Integer, primary_key=True, autoincrement=False)
    teams = relationship('Team', secondary=teams_users, back_populates="users")

    class Team(Base):
    __tablename__ = 'teams'
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    game_id = Column(Integer, ForeignKey('games.id'), nullable=False)
    games = relationship("Game", foreign_keys='games.id')
    users = relationship("User", secondary='teams_users', back_populates="teams")

    class Game(Base):
    __tablename__ = 'games'
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    team1_id = Column(Integer, ForeignKey('teams.id'))
    team2_id = Column(Integer, ForeignKey('teams.id'))
    team1 = relationship("Team", back_populates="games", foreign_keys=team1_id, uselist=False)
    tean2 = relationship("Team", back_populates="games", foreign_keys=team2_id, uselist=False)

    # done declaring, trigger the error
    configure_mappers()


    Attempting to query any of these relations returns a 'Table' object has no attribute 'id' error:



    Traceback (most recent call last):
    File "...", line 35, in <module>
    configure_mappers()
    File "/.../sqlalchemy/orm/mapper.py", line 3033, in configure_mappers
    mapper._post_configure_properties()
    File "/.../sqlalchemy/orm/mapper.py", line 1832, in _post_configure_properties
    prop.init()
    File "/.../sqlalchemy/orm/interfaces.py", line 183, in init
    self.do_init()
    File "/.../sqlalchemy/orm/relationships.py", line 1655, in do_init
    self._process_dependent_arguments()
    File "/.../sqlalchemy/orm/relationships.py", line 1680, in _process_dependent_arguments
    setattr(self, attr, attr_value())
    File "/.../sqlalchemy/ext/declarative/clsregistry.py", line 281, in __call__
    x = eval(self.arg, globals(), self._dict)
    File "<string>", line 1, in <module>
    AttributeError: 'Table' object has no attribute 'id'


    My goal in constructing it this way is that I could easily check which Teams each User has ever been a part of.



    Additionally, Game has two foreign keys into Team because the use case for this project supports arbitrarily sized teams, but only ever two teams. This allows me to have a result of "team1 won" and immediately have a reference to the winning users for stat tracking and historical reference.



    What am I doing wrong here?










    share|improve this question


























      1












      1








      1








      I've got a relationship set up across three separate classes using SQLAlchemy, with an association table for a many-to-many relationship. Minimal example:



      from sqlalchemy import * 
      from sqlalchemy.ext.declarative import declarative_base
      from sqlalchemy.orm import configure_mappers, relationship

      Base = declarative_base()

      teams_users = Table(
      'teams_users', Base.metadata,
      Column('team_id', ForeignKey('teams.id')),
      Column('user_id', ForeignKey('users.id'))
      )

      class User(Base):
      __tablename__ = 'users'
      # No autoincrement, since we're using externally-generated UIDs
      id = Column(Integer, primary_key=True, autoincrement=False)
      teams = relationship('Team', secondary=teams_users, back_populates="users")

      class Team(Base):
      __tablename__ = 'teams'
      id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
      game_id = Column(Integer, ForeignKey('games.id'), nullable=False)
      games = relationship("Game", foreign_keys='games.id')
      users = relationship("User", secondary='teams_users', back_populates="teams")

      class Game(Base):
      __tablename__ = 'games'
      id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
      team1_id = Column(Integer, ForeignKey('teams.id'))
      team2_id = Column(Integer, ForeignKey('teams.id'))
      team1 = relationship("Team", back_populates="games", foreign_keys=team1_id, uselist=False)
      tean2 = relationship("Team", back_populates="games", foreign_keys=team2_id, uselist=False)

      # done declaring, trigger the error
      configure_mappers()


      Attempting to query any of these relations returns a 'Table' object has no attribute 'id' error:



      Traceback (most recent call last):
      File "...", line 35, in <module>
      configure_mappers()
      File "/.../sqlalchemy/orm/mapper.py", line 3033, in configure_mappers
      mapper._post_configure_properties()
      File "/.../sqlalchemy/orm/mapper.py", line 1832, in _post_configure_properties
      prop.init()
      File "/.../sqlalchemy/orm/interfaces.py", line 183, in init
      self.do_init()
      File "/.../sqlalchemy/orm/relationships.py", line 1655, in do_init
      self._process_dependent_arguments()
      File "/.../sqlalchemy/orm/relationships.py", line 1680, in _process_dependent_arguments
      setattr(self, attr, attr_value())
      File "/.../sqlalchemy/ext/declarative/clsregistry.py", line 281, in __call__
      x = eval(self.arg, globals(), self._dict)
      File "<string>", line 1, in <module>
      AttributeError: 'Table' object has no attribute 'id'


      My goal in constructing it this way is that I could easily check which Teams each User has ever been a part of.



      Additionally, Game has two foreign keys into Team because the use case for this project supports arbitrarily sized teams, but only ever two teams. This allows me to have a result of "team1 won" and immediately have a reference to the winning users for stat tracking and historical reference.



      What am I doing wrong here?










      share|improve this question
















      I've got a relationship set up across three separate classes using SQLAlchemy, with an association table for a many-to-many relationship. Minimal example:



      from sqlalchemy import * 
      from sqlalchemy.ext.declarative import declarative_base
      from sqlalchemy.orm import configure_mappers, relationship

      Base = declarative_base()

      teams_users = Table(
      'teams_users', Base.metadata,
      Column('team_id', ForeignKey('teams.id')),
      Column('user_id', ForeignKey('users.id'))
      )

      class User(Base):
      __tablename__ = 'users'
      # No autoincrement, since we're using externally-generated UIDs
      id = Column(Integer, primary_key=True, autoincrement=False)
      teams = relationship('Team', secondary=teams_users, back_populates="users")

      class Team(Base):
      __tablename__ = 'teams'
      id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
      game_id = Column(Integer, ForeignKey('games.id'), nullable=False)
      games = relationship("Game", foreign_keys='games.id')
      users = relationship("User", secondary='teams_users', back_populates="teams")

      class Game(Base):
      __tablename__ = 'games'
      id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
      team1_id = Column(Integer, ForeignKey('teams.id'))
      team2_id = Column(Integer, ForeignKey('teams.id'))
      team1 = relationship("Team", back_populates="games", foreign_keys=team1_id, uselist=False)
      tean2 = relationship("Team", back_populates="games", foreign_keys=team2_id, uselist=False)

      # done declaring, trigger the error
      configure_mappers()


      Attempting to query any of these relations returns a 'Table' object has no attribute 'id' error:



      Traceback (most recent call last):
      File "...", line 35, in <module>
      configure_mappers()
      File "/.../sqlalchemy/orm/mapper.py", line 3033, in configure_mappers
      mapper._post_configure_properties()
      File "/.../sqlalchemy/orm/mapper.py", line 1832, in _post_configure_properties
      prop.init()
      File "/.../sqlalchemy/orm/interfaces.py", line 183, in init
      self.do_init()
      File "/.../sqlalchemy/orm/relationships.py", line 1655, in do_init
      self._process_dependent_arguments()
      File "/.../sqlalchemy/orm/relationships.py", line 1680, in _process_dependent_arguments
      setattr(self, attr, attr_value())
      File "/.../sqlalchemy/ext/declarative/clsregistry.py", line 281, in __call__
      x = eval(self.arg, globals(), self._dict)
      File "<string>", line 1, in <module>
      AttributeError: 'Table' object has no attribute 'id'


      My goal in constructing it this way is that I could easily check which Teams each User has ever been a part of.



      Additionally, Game has two foreign keys into Team because the use case for this project supports arbitrarily sized teams, but only ever two teams. This allows me to have a result of "team1 won" and immediately have a reference to the winning users for stat tracking and historical reference.



      What am I doing wrong here?







      python sqlalchemy






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 7 at 15:49









      Martijn Pieters

      723k14125392343




      723k14125392343










      asked Mar 7 at 15:34









      Mikey T.K.Mikey T.K.

      6111131




      6111131






















          1 Answer
          1






          active

          oldest

          votes


















          2














          To define the relationship between a game and the two teams that play in it, you need to only give the games table foreign keys; a team can play in multiple games, a one-to-many relationship; remove the games_id column altogether. The exception you got is a bit of a red herring, but it fails to properly configure the foreign_keys='games.id' argument in a relationship that doesn't need that foreign key.



          The relationship configuration on the Team class is a little tricky here as the Team.games attribute would have to relate to either foreign key. This is covered in the documentation under Handling Multiple Join Paths; you were almost there but there is no uselist parameter needed here:



          class Game(Base):
          __tablename__ = 'games'
          id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
          team1_id = Column(Integer, ForeignKey('teams.id'))
          team2_id = Column(Integer, ForeignKey('teams.id'))
          team1 = relationship("Team", foreign_keys=team1_id)
          team2 = relationship("Team", foreign_keys=team2_id)


          Note that I omitted the back_populates references here, because two relationships updating a single relationship on the other site leads one or the other of the two foreign keys being updated with the other value, leading to a game between the same team on either side!



          The inverse relationship attribute, Team.games, requires a custom primaryjoin because you are looking for games where either team1_id or team2_id is the foreign key pointing back. Use the foreign() annotation to help SQLAlchemy determine when to update the relationship (it'll watch for the foreign key changes), and use a lambda to defer resolving the columns:



          class Team(Base):
          __tablename__ = 'teams'
          id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
          # game_id = Column(Integer, ForeignKey('games.c.id'), nullable=False)
          games = relationship(
          "Game",
          primaryjoin=lambda: or_(
          Team.id == foreign(Game.team1_id),
          Team.id == foreign(Game.team2_id)
          ),
          viewonly=True,
          )
          users = relationship("User", secondary='teams_users', back_populates="teams")


          You could also make primaryjoin a string containing the expression now being executed in a lambda, so 'or_(Team.id == foreign(Game.team1_id), Team.id == foreign(Game.team2_id))'.



          Again, no back_populates, this type of relationship can't automatically update relationships between loaded objects. If you need to see these relationships reflected before committing, you'll need to issue a session flush. I also added viewonly=True, because you can't map mutations to the Team.games list to updates in the database (what would adding a new game to the list mean, that this team is team 1 or team 2?).



          You may want to add a custom constraint table to ensure that games never take place between the same team on both sides:



          class Game(Base):
          # ...
          __table_args__ = (
          CheckConstraint(team1_id != team2_id, name='different_teams'),
          )


          A quick demonstration of the relationships:



          from itertools import combinations

          engine = create_engine('sqlite:///:memory:', echo=False)
          Base.metadata.create_all(engine)
          session = sessionmaker(bind=engine)()

          teams = [Team() for _ in range(3)]
          session.add_all(teams)
          user = User(id=42, teams=teams)
          session.add(user)

          games = [Game(team1=t1, team2=t2) for t1, t2 in combinations(teams, 2)]
          session.add_all(games)
          session.commit()

          for team in user.teams:
          print('Team:', team.id, 'games:', [g.id for g in team.games])
          for game in session.query(Game):
          print(f'Game game.id: team game.team1.id vs game.team2.id')


          which outputs:



          Team: 2 games: [1, 3]
          Team: 1 games: [1, 2]
          Team: 3 games: [2, 3]
          Game 1: team 1 vs 2
          Game 2: team 1 vs 3
          Game 3: team 2 vs 3





          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55047510%2ftable-object-has-no-attribute-id-on-sqlalchemy-relation%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            To define the relationship between a game and the two teams that play in it, you need to only give the games table foreign keys; a team can play in multiple games, a one-to-many relationship; remove the games_id column altogether. The exception you got is a bit of a red herring, but it fails to properly configure the foreign_keys='games.id' argument in a relationship that doesn't need that foreign key.



            The relationship configuration on the Team class is a little tricky here as the Team.games attribute would have to relate to either foreign key. This is covered in the documentation under Handling Multiple Join Paths; you were almost there but there is no uselist parameter needed here:



            class Game(Base):
            __tablename__ = 'games'
            id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
            team1_id = Column(Integer, ForeignKey('teams.id'))
            team2_id = Column(Integer, ForeignKey('teams.id'))
            team1 = relationship("Team", foreign_keys=team1_id)
            team2 = relationship("Team", foreign_keys=team2_id)


            Note that I omitted the back_populates references here, because two relationships updating a single relationship on the other site leads one or the other of the two foreign keys being updated with the other value, leading to a game between the same team on either side!



            The inverse relationship attribute, Team.games, requires a custom primaryjoin because you are looking for games where either team1_id or team2_id is the foreign key pointing back. Use the foreign() annotation to help SQLAlchemy determine when to update the relationship (it'll watch for the foreign key changes), and use a lambda to defer resolving the columns:



            class Team(Base):
            __tablename__ = 'teams'
            id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
            # game_id = Column(Integer, ForeignKey('games.c.id'), nullable=False)
            games = relationship(
            "Game",
            primaryjoin=lambda: or_(
            Team.id == foreign(Game.team1_id),
            Team.id == foreign(Game.team2_id)
            ),
            viewonly=True,
            )
            users = relationship("User", secondary='teams_users', back_populates="teams")


            You could also make primaryjoin a string containing the expression now being executed in a lambda, so 'or_(Team.id == foreign(Game.team1_id), Team.id == foreign(Game.team2_id))'.



            Again, no back_populates, this type of relationship can't automatically update relationships between loaded objects. If you need to see these relationships reflected before committing, you'll need to issue a session flush. I also added viewonly=True, because you can't map mutations to the Team.games list to updates in the database (what would adding a new game to the list mean, that this team is team 1 or team 2?).



            You may want to add a custom constraint table to ensure that games never take place between the same team on both sides:



            class Game(Base):
            # ...
            __table_args__ = (
            CheckConstraint(team1_id != team2_id, name='different_teams'),
            )


            A quick demonstration of the relationships:



            from itertools import combinations

            engine = create_engine('sqlite:///:memory:', echo=False)
            Base.metadata.create_all(engine)
            session = sessionmaker(bind=engine)()

            teams = [Team() for _ in range(3)]
            session.add_all(teams)
            user = User(id=42, teams=teams)
            session.add(user)

            games = [Game(team1=t1, team2=t2) for t1, t2 in combinations(teams, 2)]
            session.add_all(games)
            session.commit()

            for team in user.teams:
            print('Team:', team.id, 'games:', [g.id for g in team.games])
            for game in session.query(Game):
            print(f'Game game.id: team game.team1.id vs game.team2.id')


            which outputs:



            Team: 2 games: [1, 3]
            Team: 1 games: [1, 2]
            Team: 3 games: [2, 3]
            Game 1: team 1 vs 2
            Game 2: team 1 vs 3
            Game 3: team 2 vs 3





            share|improve this answer





























              2














              To define the relationship between a game and the two teams that play in it, you need to only give the games table foreign keys; a team can play in multiple games, a one-to-many relationship; remove the games_id column altogether. The exception you got is a bit of a red herring, but it fails to properly configure the foreign_keys='games.id' argument in a relationship that doesn't need that foreign key.



              The relationship configuration on the Team class is a little tricky here as the Team.games attribute would have to relate to either foreign key. This is covered in the documentation under Handling Multiple Join Paths; you were almost there but there is no uselist parameter needed here:



              class Game(Base):
              __tablename__ = 'games'
              id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
              team1_id = Column(Integer, ForeignKey('teams.id'))
              team2_id = Column(Integer, ForeignKey('teams.id'))
              team1 = relationship("Team", foreign_keys=team1_id)
              team2 = relationship("Team", foreign_keys=team2_id)


              Note that I omitted the back_populates references here, because two relationships updating a single relationship on the other site leads one or the other of the two foreign keys being updated with the other value, leading to a game between the same team on either side!



              The inverse relationship attribute, Team.games, requires a custom primaryjoin because you are looking for games where either team1_id or team2_id is the foreign key pointing back. Use the foreign() annotation to help SQLAlchemy determine when to update the relationship (it'll watch for the foreign key changes), and use a lambda to defer resolving the columns:



              class Team(Base):
              __tablename__ = 'teams'
              id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
              # game_id = Column(Integer, ForeignKey('games.c.id'), nullable=False)
              games = relationship(
              "Game",
              primaryjoin=lambda: or_(
              Team.id == foreign(Game.team1_id),
              Team.id == foreign(Game.team2_id)
              ),
              viewonly=True,
              )
              users = relationship("User", secondary='teams_users', back_populates="teams")


              You could also make primaryjoin a string containing the expression now being executed in a lambda, so 'or_(Team.id == foreign(Game.team1_id), Team.id == foreign(Game.team2_id))'.



              Again, no back_populates, this type of relationship can't automatically update relationships between loaded objects. If you need to see these relationships reflected before committing, you'll need to issue a session flush. I also added viewonly=True, because you can't map mutations to the Team.games list to updates in the database (what would adding a new game to the list mean, that this team is team 1 or team 2?).



              You may want to add a custom constraint table to ensure that games never take place between the same team on both sides:



              class Game(Base):
              # ...
              __table_args__ = (
              CheckConstraint(team1_id != team2_id, name='different_teams'),
              )


              A quick demonstration of the relationships:



              from itertools import combinations

              engine = create_engine('sqlite:///:memory:', echo=False)
              Base.metadata.create_all(engine)
              session = sessionmaker(bind=engine)()

              teams = [Team() for _ in range(3)]
              session.add_all(teams)
              user = User(id=42, teams=teams)
              session.add(user)

              games = [Game(team1=t1, team2=t2) for t1, t2 in combinations(teams, 2)]
              session.add_all(games)
              session.commit()

              for team in user.teams:
              print('Team:', team.id, 'games:', [g.id for g in team.games])
              for game in session.query(Game):
              print(f'Game game.id: team game.team1.id vs game.team2.id')


              which outputs:



              Team: 2 games: [1, 3]
              Team: 1 games: [1, 2]
              Team: 3 games: [2, 3]
              Game 1: team 1 vs 2
              Game 2: team 1 vs 3
              Game 3: team 2 vs 3





              share|improve this answer



























                2












                2








                2







                To define the relationship between a game and the two teams that play in it, you need to only give the games table foreign keys; a team can play in multiple games, a one-to-many relationship; remove the games_id column altogether. The exception you got is a bit of a red herring, but it fails to properly configure the foreign_keys='games.id' argument in a relationship that doesn't need that foreign key.



                The relationship configuration on the Team class is a little tricky here as the Team.games attribute would have to relate to either foreign key. This is covered in the documentation under Handling Multiple Join Paths; you were almost there but there is no uselist parameter needed here:



                class Game(Base):
                __tablename__ = 'games'
                id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
                team1_id = Column(Integer, ForeignKey('teams.id'))
                team2_id = Column(Integer, ForeignKey('teams.id'))
                team1 = relationship("Team", foreign_keys=team1_id)
                team2 = relationship("Team", foreign_keys=team2_id)


                Note that I omitted the back_populates references here, because two relationships updating a single relationship on the other site leads one or the other of the two foreign keys being updated with the other value, leading to a game between the same team on either side!



                The inverse relationship attribute, Team.games, requires a custom primaryjoin because you are looking for games where either team1_id or team2_id is the foreign key pointing back. Use the foreign() annotation to help SQLAlchemy determine when to update the relationship (it'll watch for the foreign key changes), and use a lambda to defer resolving the columns:



                class Team(Base):
                __tablename__ = 'teams'
                id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
                # game_id = Column(Integer, ForeignKey('games.c.id'), nullable=False)
                games = relationship(
                "Game",
                primaryjoin=lambda: or_(
                Team.id == foreign(Game.team1_id),
                Team.id == foreign(Game.team2_id)
                ),
                viewonly=True,
                )
                users = relationship("User", secondary='teams_users', back_populates="teams")


                You could also make primaryjoin a string containing the expression now being executed in a lambda, so 'or_(Team.id == foreign(Game.team1_id), Team.id == foreign(Game.team2_id))'.



                Again, no back_populates, this type of relationship can't automatically update relationships between loaded objects. If you need to see these relationships reflected before committing, you'll need to issue a session flush. I also added viewonly=True, because you can't map mutations to the Team.games list to updates in the database (what would adding a new game to the list mean, that this team is team 1 or team 2?).



                You may want to add a custom constraint table to ensure that games never take place between the same team on both sides:



                class Game(Base):
                # ...
                __table_args__ = (
                CheckConstraint(team1_id != team2_id, name='different_teams'),
                )


                A quick demonstration of the relationships:



                from itertools import combinations

                engine = create_engine('sqlite:///:memory:', echo=False)
                Base.metadata.create_all(engine)
                session = sessionmaker(bind=engine)()

                teams = [Team() for _ in range(3)]
                session.add_all(teams)
                user = User(id=42, teams=teams)
                session.add(user)

                games = [Game(team1=t1, team2=t2) for t1, t2 in combinations(teams, 2)]
                session.add_all(games)
                session.commit()

                for team in user.teams:
                print('Team:', team.id, 'games:', [g.id for g in team.games])
                for game in session.query(Game):
                print(f'Game game.id: team game.team1.id vs game.team2.id')


                which outputs:



                Team: 2 games: [1, 3]
                Team: 1 games: [1, 2]
                Team: 3 games: [2, 3]
                Game 1: team 1 vs 2
                Game 2: team 1 vs 3
                Game 3: team 2 vs 3





                share|improve this answer















                To define the relationship between a game and the two teams that play in it, you need to only give the games table foreign keys; a team can play in multiple games, a one-to-many relationship; remove the games_id column altogether. The exception you got is a bit of a red herring, but it fails to properly configure the foreign_keys='games.id' argument in a relationship that doesn't need that foreign key.



                The relationship configuration on the Team class is a little tricky here as the Team.games attribute would have to relate to either foreign key. This is covered in the documentation under Handling Multiple Join Paths; you were almost there but there is no uselist parameter needed here:



                class Game(Base):
                __tablename__ = 'games'
                id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
                team1_id = Column(Integer, ForeignKey('teams.id'))
                team2_id = Column(Integer, ForeignKey('teams.id'))
                team1 = relationship("Team", foreign_keys=team1_id)
                team2 = relationship("Team", foreign_keys=team2_id)


                Note that I omitted the back_populates references here, because two relationships updating a single relationship on the other site leads one or the other of the two foreign keys being updated with the other value, leading to a game between the same team on either side!



                The inverse relationship attribute, Team.games, requires a custom primaryjoin because you are looking for games where either team1_id or team2_id is the foreign key pointing back. Use the foreign() annotation to help SQLAlchemy determine when to update the relationship (it'll watch for the foreign key changes), and use a lambda to defer resolving the columns:



                class Team(Base):
                __tablename__ = 'teams'
                id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
                # game_id = Column(Integer, ForeignKey('games.c.id'), nullable=False)
                games = relationship(
                "Game",
                primaryjoin=lambda: or_(
                Team.id == foreign(Game.team1_id),
                Team.id == foreign(Game.team2_id)
                ),
                viewonly=True,
                )
                users = relationship("User", secondary='teams_users', back_populates="teams")


                You could also make primaryjoin a string containing the expression now being executed in a lambda, so 'or_(Team.id == foreign(Game.team1_id), Team.id == foreign(Game.team2_id))'.



                Again, no back_populates, this type of relationship can't automatically update relationships between loaded objects. If you need to see these relationships reflected before committing, you'll need to issue a session flush. I also added viewonly=True, because you can't map mutations to the Team.games list to updates in the database (what would adding a new game to the list mean, that this team is team 1 or team 2?).



                You may want to add a custom constraint table to ensure that games never take place between the same team on both sides:



                class Game(Base):
                # ...
                __table_args__ = (
                CheckConstraint(team1_id != team2_id, name='different_teams'),
                )


                A quick demonstration of the relationships:



                from itertools import combinations

                engine = create_engine('sqlite:///:memory:', echo=False)
                Base.metadata.create_all(engine)
                session = sessionmaker(bind=engine)()

                teams = [Team() for _ in range(3)]
                session.add_all(teams)
                user = User(id=42, teams=teams)
                session.add(user)

                games = [Game(team1=t1, team2=t2) for t1, t2 in combinations(teams, 2)]
                session.add_all(games)
                session.commit()

                for team in user.teams:
                print('Team:', team.id, 'games:', [g.id for g in team.games])
                for game in session.query(Game):
                print(f'Game game.id: team game.team1.id vs game.team2.id')


                which outputs:



                Team: 2 games: [1, 3]
                Team: 1 games: [1, 2]
                Team: 3 games: [2, 3]
                Game 1: team 1 vs 2
                Game 2: team 1 vs 3
                Game 3: team 2 vs 3






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Mar 7 at 17:51

























                answered Mar 7 at 15:55









                Martijn PietersMartijn Pieters

                723k14125392343




                723k14125392343





























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55047510%2ftable-object-has-no-attribute-id-on-sqlalchemy-relation%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    1928 у кіно

                    Захаров Федір Захарович

                    Ель Греко