'Table' object has no attribute 'id' on SQLAlchemy relation2019 Community Moderator ElectionHow 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?

Why Choose Less Effective Armour Types?

What is a ^ b and (a & b) << 1?

As a new Ubuntu desktop 18.04 LTS user, do I need to use ufw for a firewall or is iptables sufficient?

What exactly is this small puffer fish doing and how did it manage to accomplish such a feat?

"Words were different when they (lived / were living) inside of you"

Official degrees of earth’s rotation per day

Print a physical multiplication table

Is it insecure to send a password in a `curl` command?

Simplify an interface for flexibly applying rules to periods of time

Knife as defense against stray dogs

If I can solve Sudoku, can I solve the Travelling Salesman Problem (TSP)? If so, how?

How difficult is it to simply disable/disengage the MCAS on Boeing 737 Max 8 & 9 Aircraft?

Explaining pyrokinesis powers

What is the adequate fee for a reveal operation?

Is there a hypothetical scenario that would make Earth uninhabitable for humans, but not for (the majority of) other animals?

Happy pi day, everyone!

Relationship between sampajanna definitions in SN 47.2 and SN 47.35

If I am holding an item before I cast Blink, will it move with me through the Ethereal Plane?

Examples of transfinite towers

How to pronounce "I ♥ Huckabees"?

Describing a chess game in a novel

A single argument pattern definition applies to multiple-argument patterns?

ERC721: How to get the owned tokens of an address

Why is the President allowed to veto a cancellation of emergency powers?



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



2019 Community Moderator ElectionHow 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

      720k14025172323




      720k14025172323










      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

                720k14025172323




                720k14025172323





























                    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

                    Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

                    2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived

                    Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme