tags:

views:

137

answers:

2

Suppose I have 3 classes in SQLALchemy: Topic, Tag, Tag_To_Topic.

Is it possible to write something like:

new_topic = Topic("new topic")
Topics.tags = ['tag1', 'tag2', 'tag3']

Which I would like to automatically insert 'tag1', 'tag2' and 'tag3' in Tag table, and also insert the correct relationship between new_topic and these 3 tags in Tag_To_Topic table.

So far I haven't been able to figure out how to do this because of many-to-many relationship. (If it was a one-to-many, it would be very easy, SQLAlchemy would does it by default already. But this is many-to-many.)

Is this possible?

Thanks, Boda Cydo.

+3  A: 

Fist of all you could simplify your many-to-many relation by using association_proxy.

Then, I would leave the relation as it is in order not to interfere with what SA does:

# here *tag_to_topic* is the relation Table object
Topic.tags = relation('Tag', secondary=tag_to_topic)

And I suggest that you just create a simple wrapper property that does the job of translating the string list to the relation objects (you probably will rename the relation). Your Tags class would look similar to:

class Topic(Base):
    __tablename__ = 'topic'
    id = Column(Integer, primary_key=True)
    # ... other properties

    def _find_or_create_tag(self, tag):
        q = Tag.query.filter_by(name=tag)
        t = q.first()
        if not(t):
            t = Tag(tag)
        return t

    def _get_tags(self):
        return [x.name for x in self.tags]

    def _set_tags(self, value):
        # clear the list first
        while self.tags:
            del self.tags[0]
        # add new tags
        for tag in value:
            self.tags.append(self._find_or_create_tag(tag))

    str_tags = property(_get_tags,
                        _set_tags,
                        "Property str_tags is a simple wrapper for tags relation")

Then this code should work:

# Test
o = Topic()
session.add(o)
session.commit()
o.str_tags = ['tag1']
o.str_tags = ['tag1', 'tag4']
session.commit()
van
I am trying this now. Huge thanks for helping!
bodacydo
I would like to express my deep gratitude to you, Van, for helping me. Your suggestion of using association proxy, and improving the class by adding helper methods resulted great code and solution. Thanks!
bodacydo
A: 

Could you post the final code, Boda? I have a similar problem and I'd like to see the full details of your example.

Brent Ramerth
Sure, I will be at work tomorrow, and will post then.
bodacydo