7

我想以这样的方式使用 sqlalchemy:

email1 = EmailModel(email="user@domain.com", account=AccountModel(name="username"))
email2 = EmailModel(email="otheruser@domain.com", account=AccountModel(name="username"))

通常 sqlalchemy 将为帐户创建两个条目并将每个电子邮件地址链接到此。如果我将帐户名设置为唯一 sqlalchemy 会引发异常,告诉我已经存在具有相同值的条目。这很有意义并且按预期工作。

现在我自己想出了一种方法,它允许上述代码,并且只通过覆盖AccountModel 类的新构造函数来创建一个帐户:

def __new__(*cls, **kw):
    if len(kw) and "name" in kw:
        x = session.query(cls.__class__).filter(cls[0].name==kw["name"]).first()
        if x: return x
    return object.__new__(*cls, **kw)

这对我来说非常有效。但问题是:

  • 这是正确的方法吗?
  • 是否有实现相同目标的 sqlalchemy 方法?

我正在使用最新的 0.8.x SQLAlchemy 版本和 Python 2.7.x

谢谢你的帮助 :)

4

2 回答 2

7

在http://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObject的 wiki 上有这个例子。

不过,最近我更喜欢使用 a@classmethod而不是重新定义构造函数,因为显式优于隐式,也更简单:

user.email = Email.as_unique('foo@bar.com')

(实际上,我现在要更新 wiki 以更全面地代表此处的使用选项。)

于 2012-11-18T14:49:38.413 回答
1

我认为这不是实现这一点的最佳方法,因为它会创建构造函数对全局变量的依赖关系,session并且还会以意想不到的方式修改构造函数的行为(毕竟new预计会返回一个新对象)。例如,如果有人将您的类与两个并行会话一起使用,则代码将失败,他将不得不深入研究代码以查找错误。

我不知道有任何“sqlalchemy”方法来实现这一点,但我建议创建一个createOrGetAccountModel类似的函数

def createOrGetAccountModel(**kw):
    if len(kw) and "name" in kw:
      x = session.query(AccountModel).filter_by(name=kw["name"]).first()
      if x: return x
    return AccountModel(**kw)
于 2012-11-18T14:39:28.243 回答