SQLAlchemy - MappedCollection 问题

3 投票
3 回答
740 浏览
提问于 2025-04-15 11:16

我在使用Python的SQLAlchemy设置字典集合时遇到了一些问题:

我在定义表的时候使用了声明式的方法。我有一个Item表,它和Record表之间是1对多的关系。我用下面的代码设置了这个关系:

_Base = declarative_base()

class Record(_Base):
    __tablename__ = 'records'

    item_id = Column(String(M_ITEM_ID), ForeignKey('items.id'))
    id = Column(String(M_RECORD_ID), primary_key=True)
    uri = Column(String(M_RECORD_URI))
    name = Column(String(M_RECORD_NAME))

class Item(_Base):
    __tablename__ = 'items'

    id = Column(String(M_ITEM_ID), primary_key=True)

    records = relation(Record, collection_class=column_mapped_collection(Record.name), backref='item')

现在我想处理这些ItemRecord。我们来创建一些对象:

i1 = Item(id='id1')
r = Record(id='mujrecord')

接下来,我想用下面的代码把这些对象关联起来:

i1.records['source_wav'] = r

但是Record r没有设置name属性(也就是外键)。有没有什么办法可以自动确保这一点?(我知道在创建Record的时候设置外键是可行的,但我觉得这样不太好)。

非常感谢

3 个回答

0

你有:

backref='item'

这是一个关于

backref='name'

的拼写错误吗?

1

我还不能评论,所以我就把这个当作一个单独的回答来写:

from sqlalchemy.orm import validates

class Item(_Base):
    [...]

    @validates('records')
    def validate_record(self, key, record):
      record.name=key
      return record

这基本上是Gunnlaugur的回答的复制版,不过我利用了验证装饰器来做一些比出错更有用的事情。

2

你想要的效果是这样的:

from sqlalchemy.orm import validates

class Item(_Base):
    [...]

    @validates('records')
    def validate_record(self, key, record):
      assert record.name is not None, "Record fails validation, must have a name"
      return record

通过这个,你就能得到想要的验证效果:

>>> i1 = Item(id='id1')
>>> r = Record(id='mujrecord')
>>> i1.records['source_wav'] = r
Traceback (most recent call last):
  [...]
AssertionError: Record fails validation, must have a name
>>> r.name = 'foo'
>>> i1.records['source_wav'] = r
>>> 

撰写回答