首先,示例代码:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy import event
Base = declarative_base()
class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
label = Column(String)
class Bar(Base):
__tablename__ = 'bar'
id = Column(Integer, primary_key=True)
foo_id = Column(Integer, ForeignKey('foo.id'))
foo = relationship(Foo)
def __init__(self, foo=None):
self.foo = foo if foo else Foo()
print 'init', self.id, self, self.foo.id, self.foo
def _adjust_label(target, value, old_value, initiator):
print 'adjust', target, value, old_value, initiator
if value and not target.foo.label:
target.foo.label = 'autostring %d' % value
print 'adjust', target.id, target, target.foo.id, target.foo, target.foo.label
event.listen(Bar.id, 'set', _adjust_label)
engine = create_engine('sqlite:////path/to/some.db')
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
bar = Bar()
print 'pre-add', bar.id, bar, bar.foo.id, bar.foo
session.add(bar)
print 'added', bar.id, bar, bar.foo.id, bar.foo
session.commit()
print 'commited', bar.id, bar, bar.foo.id, bar.foo, bar.foo.label
我得到的是:
pre-add None <__main__.Bar object at 0x2929f50>
pre-add None <__main__.Foo object at 0x292e310>
added None <__main__.Bar object at 0x2929f50>
added None <__main__.Foo object at 0x292e310>
adjust <__main__.Bar object at 0x2929f50> 14 None Bar.id
adjust None <__main__.Bar object at 0x2929f50>
adjust 14 <__main__.Foo object at 0x292e310> autostring 14
commited 14 <__main__.Bar object at 0x2929f50>
commited 14 <__main__.Foo object at 0x2932e10> None
令我惊讶的是, in与提交之前的实例不同committed
,bar.foo
显然结果是,我bar.foo.label
对事件侦听器的成功更改被抛出了窗口。我正在尝试这样做,因为我需要一个自动生成的唯一字符串bar.foo.label
,并且我想要比纯随机字符串更有意义的东西。是否可以在有或没有事件监听器的情况下自动执行此操作,或者我是否必须在比 ORM 模型更高的级别上处理它?