SQLAlchemy:返回现有对象,而不是在调用构造函数时创建新的on

时间:2012-11-18 14:07:46

标签: python object model constructor sqlalchemy

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

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

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

现在我想出了一个我自己的方法,它允许提到的代码,只是通过覆盖AccountModel类的 new 构造函数来创建一个帐户:

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)

这对我来说非常合适。但问题是:

  • 这是正确的方法吗?
  • 是否有一种方法可以实现同样的目标?

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

感谢您的帮助:)

2 个答案:

答案 0 :(得分:6)

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

虽然最近我更倾向于使用@classmethod而不是重新定义构造函数,因为显式优于隐式,也更简单:

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

(我实际上现在要更新维基以更全面地代表这里的使用选项)

答案 1 :(得分:1)

我认为这不是实现此目的的最佳方法,因为它会创建构造函数与全局变量session的依赖关系,并且还会以意外的方式修改构造函数的行为(new是预期的毕竟返回一个 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)