假设我有类Dog(),Walrus(),Boot()。 我想做它,所以你不能更新Walrus对象,虽然你可以删除它们,你永远不能删除Boot对象。 所以如果:
dog1 = Dog("DogName")
walrus1 = Walrus("WalrusName")
boot1 = Boot("BootName")
session.add(dog1)
session.add(walrus1)
session.add(boot1)
session.flush()
transaction.commit()
dog1.name = "Fluffy"
walrus1.name = "Josh"
boot1.name = "Pogo"
session.flush()
transaction.commit()
它会在更改海象名称时引发异常,但允许更改其他名称。 如果我试图删除boot1,它会抛出异常。
我对事件听众采取了一些刺激,但我接近的两种方式并没有让我一直到那里:
#One possibility
#I don't know how to tell that it's just an update though
#The is_modified seems to take inserts as well
@event.listens_for(Session, 'before_flush')
def listener(thissession, flush_context, instances):
for obj in thissession:
if isinstance(obj, Walrus):
if thissession.is_modified(obj, include_collections=False):
thissession.expunge(obj)
#Possiblity two
#It says before_update but it seems to take in inserts as well
#Also documentation says it's not completely reliable to capture all statements
#where an update will occur
@event.listens_for(Walrus, 'before_update', raw=True)
def pleasework(mapper, connection, target):
print "\n\nInstance %s being updated\n\n" % target
object_session(target).expunge(target)
编辑1:
@event.listens_for(Walrus, 'before_update', raw=True)
def prevent_walrus_update(mapper, connection, target):
print "\n\nInstance %s being updated\n\n" % target
if target not None:
raise
@event.listens_for(Boot, 'before_delete', raw=True)
def prevent_boot_delete(mapper, connection, target):
print "\n\nInstance %s being deleted\n\n" % target
if target not None:
raise
我已经让它工作了,它不允许我对Walrus进行更新或删除Boot,但任何暗示试图将崩溃的AttributeError我似乎没有任何能力抓住。例如,如果我运行Walrus1.name =“Josh”然后在al处进行任何查询,即使是get,AttributeError也会使应用程序崩溃。我比我更进一步,但仍然很不方便。
答案 0 :(得分:1)
如果您只是将循环更改为:
,那么您发布的第一个解决方案看起来应该可行for obj in thissession.dirty:
您可以使用相同的before_flush
事件来阻止通过thissession.deleted
循环删除Boot对象。