7

私は次のような方法でsqlalchemyを使用したいと思います:

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

通常、sqlalchemyはアカウントに2つのエントリを作成し、各メールアドレスをこれにリンクします。アカウント名を一意に設定すると、sqlalchemyは、同じ値のエントリがすでに存在することを通知する例外をスローします。これはすべて理にかなっており、期待どおりに機能します。

今、私は、前述のコードを許可し、AccountModelクラスの新しいコンストラクターを上書きすることによってアカウントを1回だけ作成する方法を自分で考え出しました。

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.xSQLAlchemyバージョンとPython2.7.xを使用しています

助けてくれてありがとう:)

4

2 に答える 2

7

この例は、ウィキのhttp://www.sqlalchemy.org/trac/wiki/UsageRecipes/UniqueObjectにあります。

Though, more recently I've preferred to use a @classmethod for this instead of redefining the constructor, as explicit is better than implicit, also simpler:

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

(I'm actually going to update the wiki now to more fully represent the usage options here.)

于 2012-11-18T14:49:38.413 に答える
1

コンストラクターのグローバル変数への依存関係を作成sessionし、予期しない方法でコンストラクターの動作を変更するため、これを実現するための最良の方法ではないと思います(結局、新しいオブジェクトnewを返すことが期待されます)。たとえば、誰かが2つのセッションでクラスを並行して使用している場合、コードは失敗し、エラーを見つけるためにコードを掘り下げる必要があります。

私はこれを達成するための「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 に答える