在SQLAlchemy中创建类似于set的映射属性

时间:2014-10-02 17:28:32

标签: python sql orm sqlalchemy set

我已经完成了一些阅读和谷歌搜索,但仍然不确定是否有一个本机/内置方法在SQLAlchemy对象中创建一个映射属性,它为类似的方案创建一个类似于set的属性: / p>

User                             UserTag
+----+-----------------+         +---------+-----------+
| id | email           |         | user_id | tag       |
+----+-----------------+         +---------+-----------+
| 1  | foo@example.com |         | 1       | footag    |
| 2  | bar@example.com |         | 1       | something |     
+----+-----------------+         | 1       | tagbar    |
                                 | 2       | something |
                                 | 2       | 3rdtag    |
                                 +---------+-----------+

这样每个User对象都有一个User.tags映射属性,该属性是(或表现得像)一组字符串 - 例如以下方法可行:

>>> user = session.query(User).filter(User.id == 1).one()
>>> print user.tags
set(['tagbar', 'something', 'footag'])

1 个答案:

答案 0 :(得分:0)

使用Association Proxy来实现这一目标:

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    email = Column(String, nullable=False)
    tags = relationship('UserTag', collection_class=set,
                        cascade="all, delete, delete-orphan")
    tagset = association_proxy(
        'tags', 'tag_name',
        creator=lambda tag_name: UserTag(tag_name=tag_name),
    )

class UserTag(Base):
    __tablename__ = 'user_tags'
    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    tag_name = Column(String, primary_key=True)

然后您可以采用以下方式处理模型:

# create sample data
foo = User(
    email='foo@example.com',
    tagset={'footag', 'something', 'tagbar'}
)
bar = User(
    email='bar@example.com',
    tagset={'something', '3rdtag'}
)
session.add(foo)
session.add(bar)
session.commit()

bar = session.query(User).get(2)
assert 'something' in bar.tagset
bar.tagset.remove('something')
assert 'something' not in bar.tagset

同时添加具有相同UserTag值的tag_name也将得到妥善处理。