2011-09-14 43 views
1

有人可以帮助我获得大图当涉及到配置SQLAlchemy模型,所以参考完整性在各个层面都得到保证吗?参照完整性 - 如何配置SQLAlchemy?

通过引用完整性应该由数据库表达和实施的想法,我创建了一个模式(目前在Postgresql中),并且我认为我需要所有的约束,因此给了我一个我信任的数据库来强制执行参照完整性。

然后我开始在这个数据库之上建立一个应用程序,在声明模式下使用SQLAlchemy(0.7)。

已经搜索并阅读了一下,我了解到,我可以配置:

  • 的onupdate/ondelete规则在我的专栏()的定义。
  • 我的关系()定义中的级联选项,
    并且这些似乎在SQLAlchemy中的会话级别上运行。
  • 我的关系()定义的passive_deletes和passive_updates选项。

而且所有这些选项都有默认值。

但我对我实际需要用SQLAlchemy模型做了多少事情感到困惑,以确保SQLAlchemy在会话期间不会与数据库及其约束不同步。

如果我在SQLAlchemy中的Columns()定义上配置'onupdate'等等,我到底在做什么?

而对于cascade和passive_delete/passive_update规则,我可以在关系()上进行配置。我在这里需要什么,为什么?

还是要改写我的问题:什么事情让延长会的SQLAlchemy知道在DB模式配置的限制,以及在何种扩展(以及如何)我要重复他们在我的模型?

还有什么我应该知道的? :)

回答

4

SQLAlchemy从根本上不需要知道任何有关您的数据库的约束。如果你的数据库有你想要配置的约束,那么你基本上已经完成了 - 数据库不允许你的应用程序做任何它不应该做的事情。

SQLAlchemy的一个关键主题是,它只是在做你告诉它的事情。因此,如果要尝试持久化一个对象,那么在数据库中需要引用父Widget()的SubWidget()时,SQLAlchemy刷新数据(即发出INSERT语句)时,操作将失败违反约束,由数据库发出,事务回滚。

因此,假设在“subwidget”引用“小部件”上的FK,您的应用程序需要确保数据的结构正确。有两种方法可以做到这一点;一个是你手工维护那些包含外键引用的列,并确保它们在INSERT或UPDATE点具有适当的值。另一种方法是使用relationship()来管理外键属性,并且确保SubWidget()对象的创建伴随着将它与父Widget()对象关联的操作创建和/或分开获得。

关于级联,虽然不是必需的,但在其应用的外键上具有ON DELETE CASCADE是个好主意。在SQLAlchemy方面,当使用relationship()时,通常希望向ORM提示数据库将通过passive_deletes标志级联删除(http://www.sqlalchemy.org/docs/orm/collections.html?highlight=passive_deletes#using-passive-deletes),但这通常是性能增强;否则,SQLAlchemy将确保relationship()的从属端上表示的所有对象都被加载到内存中,并进行适当处理,这意味着要么将外键属性设置为NULL(缺省值),要么标记要删除的依赖对象通过将“cascade”设置为“all,delete-orphan”,见http://www.sqlalchemy.org/docs/orm/session.html#cascades)。

ON UPDATE级联不太常见,因为自然主键最近并不常见,因为它们实际上并不像普通的整数主键那样好,而且在其他方​​面也很麻烦。然而,SQLAlchemy也支持这些方法,因为它们通常会自行处理,因为SQLA默认假设发生PK突变时更新级联就位,请参阅http://www.sqlalchemy.org/docs/orm/relationships.html#mutable-primary-keys-update-cascades以获得详细描述。

也许这一切都比较容易实践一下,基本思想是SQLAlchemy只发布你要告诉它的SQL,即使它的许多SQL行为在事先配置好后都会自动执行。 relationship()应配置详细信息,说明当数据在数据库中存在的约束条件下持续,修改或删除数据时,它的行为方式。

+0

嗨zzzeek, 感谢您尝试解除一些雾气在我的头上。而对于SQLAlchemy本身! :) 我已经为自己的问题添加了一个“答案”,在那里我总结了我认为我学到了什么。 希望我在正确的轨道上... – herira

1

所以,建立在zzzeeks答案,和我自己的学习/我最初的问题修修补补后...

为了让SQLAlchemy的积极防止的DB状态的会议期间视图可以从转移什么数据库将允许在刷新/提交时,您必须镜像SQLAlchemy模型中的数据库模式中找到的所有约束。

,这是在形式通过列定义完成:

ForeignKey(..., onupdate='', ondelete='') 
primary_key=True 
unique=True 

等,与可能列入__table_args__,如:

__table_args__ = (
     ForeignKeyConstraint(['id'], ['remote_table.id']), 
     UniqueConstraint('foo'), 
     ) 

对于情况的约束跨度多列。

鉴于:

relationship() 

及其相关参数,如:

cascade 
cascade_backrefs 
foreign_keys 
passive_deletes 
passive_updates 

等,是一个(重要)的便利功能,让您与您的模型工作,用尽可能少的努力尽可能,但最终并不意味着什么防止违反参照完整性。

关系()功能无法表示数据库中的所有典型约束,而Column()(和__table_args__)功能可以。另一方面,使用上面列出的一些参数(或者在最有意义的情况下使用缺省值)配置关系(),将使SQLAlchemy自动执行任务,最终可以说是参考整数有关。否则通常必须用周围代码中的逻辑来表示。

关系()的最佳配置在某些情况下也会避免SQLAlchemy发出不必要的SQL语句。

希望这总和不太准确......

+0

短暂的掠过似乎对我来说很好 – zzzeek