Zitrax
Zitrax

Reputation: 20246

Sqlalchemy relationship to built-in type

I have something similar to this:

class Item(Base, DBBase):
  __tablename__ = 'item'
  id = Column(Integer, primary_key = True)
  name = Column(String), nullable = True)
  comments = relationship('ItemComment')

class ItemComment(Base, DBBase):
  __tablename__ = 'itemcomments'
  item_id = Column(Integer, ForeignKey('item.id'), nullable = False, primary_key=True)
  comment = Column(String), nullable = False, primary_key=True)

I am wondering if it's possible to have the relationship map directly to the string so I can avoid handling ItemComment objects directly in the code. For example adding a new comment like this: item.comments.append("hello") or directly iterate over the string comments using for comment in item.comments:. I assume it could work with a @property, but is there a way to setup the relationship to handle it transparently ?

Upvotes: 1

Views: 92

Answers (1)

van
van

Reputation: 76962

Exactly what Association Proxy extension is doing. In your case it would mean having the model like below:

class Item(Base, DBBase):
    __tablename__ = 'item'
    id = Column(Integer, primary_key = True)
    name = Column(String, nullable = True)
    comments = relationship('ItemComment')
    comms = association_proxy('comments', 'comment',
            creator=lambda comment: ItemComment(comment=comment),
            )

class ItemComment(Base, DBBase):
    __tablename__ = 'itemcomments'
    item_id = Column(Integer, ForeignKey('item.id'), nullable = False, primary_key=True)
    comment = Column(String, nullable = False, primary_key=True)
    def __init__(self, comment):
        self.comment = comment

and you can use it exactly like you wish:

my_item.comms.append("super")
print "All Comments: ", my_item.comms

One additional comment: you either need to specify the creator parameter (like in the code above) or else it is expected that you have a one-parameter constructor on ItemComment (like above), but one of the two suffice. I usually prefer explicit creation via creator parameter.
Also, you might want to rename comments to _comments and comms to comments.

Upvotes: 2

Related Questions