在sqlalchemy中,我可以监听集合上的append
事件来拦截并可能更改要附加的值。例如,当我想用任意的标准实现一个类似set
的行为时,我该如何静默地删除该值(而不是追加)?在
MCVE(除了sqlalchemy之外没有任何依赖关系,只需复制并粘贴):
from sqlalchemy import create_engine, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.event import listens_for
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
_next_id = 1
def get_id():
global _next_id
_ = _next_id
_next_id += 1
return _
class A1(Base):
__tablename__ = 'a1'
id = Column(Integer, primary_key=True, default=get_id)
a2 = relationship('A2', back_populates='a')
class A2(Base):
__tablename__ = 'a2'
id = Column(Integer, primary_key=True, default=get_id)
a_id = Column(Integer, ForeignKey('a1.id'))
a = relationship('A1', back_populates='a2')
name = Column(Text)
@listens_for(A1.a2, 'append', retval=True)
def coll_listener(target, val, initiator):
for _ in target.a2:
if _.name == val.name:
# this is justs some arbitrary condition to illustrate things
return
return val
Base.metadata.create_all(engine)
Session = sessionmaker()
Session.configure(bind=engine)
_session = Session()
a2_1 = A2(name='a2_1')
a2_2 = A2(name='a2_2')
a2_3 = A2(name='a2_1')
a1 = A1()
for thing in (a2_1, a2_2, a2_3, a1):
_session.add(thing)
_session.flush()
for a in (a2_1, a2_2, a2_3):
a1.a2.append(a)
_session.flush()
# raises FlushError: Can't flush None value found in collection A1.a2
对我自己说,既然没人感兴趣。。。在
我现在相信在使用事件侦听器添加时不可能删除元素。所以我最终实现了一个custom collection(这并不是完全鼓励的),结果证明这相当简单:
当然,我们必须根据需要实现进一步的行为,例如
__getitem__()
/__setitem__()
/__delitem__()
用于索引等相关问题 更多 >
编程相关推荐