【问题标题】:How can I prevent specific classes from being updated/deleted in SQLAlchemy?如何防止特定类在 SQLAlchemy 中被更新/删除?
【发布时间】:2013-01-30 01:41:43
【问题描述】:

假设我有 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" 然后任何查询,即使是 get,AttributeError 都会使应用程序崩溃。我比以前走得更远了,但仍然相当不便。

【问题讨论】:

    标签: python session event-handling sqlalchemy


    【解决方案1】:

    如果您只是将循环更改为读取,您发布的第一个解决方案看起来应该可以工作:

    for obj in thissession.dirty:
    

    您可以使用相同的before_flush 事件通过循环thissession.deleted 来防止删除Boot 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多