18

I have these tables tables:

class Thing(Base):
    __tablename__ = 'thing'
    id = Column(Integer, primary_key=True)

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)

class Voteinfo(Base):
    __tablename__ = 'voteinfo'
    thing_id = Column(Integer, ForeignKey('thing.id'), primary_key=True)
    thing = relationship('Thing', backref='voteinfo')
    upvotes = Column(Integer)
    downvotes = Column(Integer)

    def __init__(self, thing)
        self.thing = thing

class VoteThing(Base):
    __tablename__ = 'votething'
    id = Column(Integer, primary_key=True)
    voter_id = Column(Integer, ForeignKey('voter.id'))
    voter = relationship('Voter', backref='votescast')
    thing_id = Column(Integer, ForeignKey('thing.id'))
    thing = relationship('Thing', backref='votesreceived')
    value = Column(Boolean)

    def __init__(self, voter, thing, value):
        if value is True:
            thing.voteinfo.upvotes += 1
        else:
            thing.voteinfo.downvotes += 1

When I try to run this, I get this error code in the "if value is True" clause:

AttributeError: 'InstrumentedList' object has no attribute 'upvotes'

I've tried giving Voteinfo its own unique ID and adding uselist=False to the relationship. I've tried replacing the relationship to thing from VoteThing to Voteinfo, but that didn't help either. I don't know what an InstrumentedList is. What is going on?

Jonathan Ong
  • 19,086
  • 15
  • 76
  • 115
  • since `thing` is a parameter to `__init__`, presumably you're passing it when you instantiate the VoteThing. So what are you passing? – Daniel Roseman Oct 06 '11 at 08:59
  • Yes, I am passing a thing: thing1 = Thing(), user1 = User(), voteinfo1 = Voteinfo(thing1), votething1 = VoteThing(user1, thing1, True) – Jonathan Ong Oct 06 '11 at 09:06

2 Answers2

27

As explained in the documentation, here : https://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#one-to-one, you have to add uselist=False not to the relationship, but to the backref.

thing = relationship('Thing', backref=backref('voteinfo', uselist=False))
dangel
  • 6,768
  • 5
  • 45
  • 70
madjar
  • 12,081
  • 2
  • 43
  • 52
0

It may been useful to add lazy='dynamic' argument to request that the query is not automatically executed and of course refresh (thing = relationship('Thing', backref='voteinfo', lazy='dynamic')), otherwise expression is issued internally call all() to return the list of 'thing' hence AttributeError: 'InstrumentedList' object has no attribute error!!