Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Key error on backref when try to setup many to many Association Object

I'm trying to setup a basic many-to-many relationship using sqlalchemy and can't pin down what I'm doing wrong. Essentially, I have a table of Users and a table of Offers (basically, something like Groupon). Users can respond to many offers, and offers can be sent to many users. I've been using this section of the sqlalchemy docs but clearly I'm doing something wrong.
Here is the relevant section of my code:

class Offer(db.Model):
     __tablename__ = 'offers'
    id = Column(Integer, primary_key=True)
    title = Column(String)
    description = Column(String)
    users = association_proxy('user_offers', 'user')

    def __init__(self, title, description):
        self.title = title
        self.description = description

class User(db.Model):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    first_name = Column(String, nullable=False)
    last_name = Column(String, nullable=False)
    email = Column(String, index=True, unique=True)

    def __init__(self, first_name, last_name, email):
        self.first_name = first_name
        self.last_name = last_name
        self.email = email.lower()

class UserOfferResponse(db.Model):
    __tablename__ = 'user_offer_responses'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    offer_id = Column(Integer, ForeignKey('offers.id'))
    response = Column(String)
    created_at = Column(DateTime)

    offer = relationship(Offer,
            backref=backref("user_offers",
                            cascade="all, delete-orphan")
        )
    user = relationship("User")

    def __init__(self, offer=None, user=None, response="", created_at=datetime.datetime.now()):
        self.response = response
        self.offer = offer
        self.user = user
        self.created_at = created_at

Using the code above, I can create an Offer and a User, but if I try to associate the two (offer.users.append(user)) I get the following error:

File "/Users/scottmorse/.virtualenvs/WhereItsApp/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 224, in __set__
    instance_dict(instance), value, None)
  File "/Users/scottmorse/.virtualenvs/WhereItsApp/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 802, in set
    value = self.fire_replace_event(state, dict_, value, old, initiator)
  File "/Users/scottmorse/.virtualenvs/WhereItsApp/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 824, in fire_replace_event
    self._replace_token or self._init_append_or_replace_token())
  File "/Users/scottmorse/.virtualenvs/WhereItsApp/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1153, in emit_backref_from_scalar_set_event
    child_impl = child_state.manager[key].impl
KeyError: 'user_offers'

Any help would be appreciated, and thanks for reading.

like image 251
Scott Avatar asked Jul 11 '15 21:07

Scott


1 Answers

Found the answer here: KeyError when adding objects to SQLAlchemy association object

Because I was trying to add a user to the offer's list, I needed to either 1) make sure that the User is the first item passed to the UserOfferResponse constructor (because that is how it will be called by the association_proxy, or 2) add an explicit 'creator' parameter to the association_proxy.

I chose option 2, as it allows me to work in "both directions". Thanks for reading!

like image 118
Scott Avatar answered Nov 05 '22 03:11

Scott