1

So using SqlAlchemy, I'm creating a fairly simple many-to-many relationship between a users model and a comments model.

users.py

class UsersModel(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String(50))
    email = Column(String(50))
    issues = relationship(IssuesModel, backref="user")
    comments = relationship(IssueCommentsModel, backref="user")
    voted_comments = association_proxy('users_comments', 'comment')

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<Users('%s', '%s', '%s')>" % (self.id,
                                              self.username,
                                              self.email)

users_comments.py

class UsersCommentsModel(Base):
    __tablename__ = 'users_comments'
    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    comment_id = Column(Integer, ForeignKey('issue_comments.id'), primary_key=True)
    vote = Column(Integer(1))

    user = relationship(UsersModel,
                        backref="users_comments")
    comment = relationship(IssueCommentsModel,
                           backref="users_comments")

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<UsersComments('%s', '%s', '%s')>" % (self.user_id,
                                                      self.comment_id,
                                                      self.vote)    

issue_comments.py

class IssueCommentsModel(Base):
    __tablename__ = 'issue_comments'

    id = Column(Integer, primary_key=True)
    body = Column(String(300))
    created = Column(DateTime)
    change_time = Column(DateTime)
    score = Column(Integer(100), default=0)
    issue_id = Column(Integer, ForeignKey('issues.id'))
    user_id = Column(Integer, ForeignKey('users.id'))
    voted_users = association_proxy('users_comments', 'user')

    def __init__(self, **fields):
        self.__dict__.update(fields)

    def __repr__(self):
        return "<IssueComments('%s', '%s', '%s', '%s', '%s', '%s')>" % (self.id, 
                                                                        self.body, 
                                                                        self.issue, 
                                                                        self.user, 
                                                                        self.created, 
                                                                        self.change_time)

Each user has the ability to both create comments, and either up/down vote them. The above code is completely working code. My question is this. When I remove the two backrefs in the UsersCommentsModel class, the code no longer works and an InvalidRequestError is thrown. It states that the users_comments attribute cannot be found on the UsersModel mapper. I thought this was strange, b/c I would think you would be able to proxy all relationships through the central users_comments relationship model, and never have to actually store an instance of that model in the users/comments models.

Question:

Is there any way to remove the backrefs, so no other attributes are stored in the users/comments models?

JayD3e
  • 2,147
  • 3
  • 21
  • 30
  • 1
    if you remove the users_comments backrefs, what is the "central users_comments relationship model" ? I don't see any other relationships that use the name "users_comments". Removing those two backrefs means that the name "users_comments" is no longer a mapped attribute, the association proxy no longer can locate what it's being told to use. – zzzeek Oct 23 '11 at 15:00
  • O ok I guess that was a subtlety that I didn't pick up on, the association_proxy actually uses a member of the model that you define it in. I was thinking that by specifying association_proxy('users_comments', {attr}), that sqla was proxying the association to the model attached to the 'users_comments' table. So I guess the main thing I'm asking, is if there is a way to take a many-to-many relationship defined through a 'secondary' table(i.e. model2s = relationship(Model2, secondary=SecondaryTable, backref="model1")) and change it to a many-to-many defined through association objects? – JayD3e Oct 23 '11 at 16:54
  • That way with all of my many-to-many relationships, I have the option of at some point adding extra fields to the association table in the middle of the relationship. – JayD3e Oct 23 '11 at 16:56
  • 1
    I think the docs at http://www.sqlalchemy.org/docs/orm/extensions/associationproxy.html, which note were rewritten in the past several months, should make these questions clear. As far as m2m to association, any m2m can be transformed to an association by removing the "secondary" argument and replacing with an explicit mapping, as in the example at http://www.sqlalchemy.org/docs/orm/relationships.html#association-object – zzzeek Oct 23 '11 at 21:07
  • Your second link cleared everything up for me completely. Thanks. – JayD3e Oct 23 '11 at 23:35

0 Answers0