2012-07-26 34 views
8

プライマリキーまたはユニークキーの競合、つまり重複エントリがある場合を処理したいと思います。このため私はIntegrityErrorを捕まえています。これはエラーをうまく捉えています。問題は、単純なエラーメッセージやエラーコードを確認できないようです。SQLAlchemyのエラー処理 - それはどのように行われますか?

(IntegrityError)(1062年、 "重複エントリ 'foobarの' キー 'name' の")

だ:私は取得していますすべては、このようになります文字列であるIntegrityError.messageプロパティですあまり役に立たない。これを使用して、コードとメッセージのエラーメッセージの解析を開始する必要があります。例外にdirを呼び出すと、次のプロパティのみを示しています

'引数'、 'connection_invalidated'、 'インスタンス'、 'メッセージ'、 'ORIG'、 'のparams'、 'ステートメント'

argsは単なる単項タプルであり、その中に前述の文字列があり、paramsは挿入しようとしたデータです。私は実際に正規表現や何かを使用してエラーメッセージを解析する必要はありませんが、これは実際に重複したキーエラーであると判断する方法を見つけることができません。

誰でもこの問題を解明できますか?より慎重にドキュメントを読んで、質問を書きながら

おかげ

答えて

12

は、私はこれを考え出しました。私はまだ誰かに助けになるかもしれないので、これを投稿するつもりです。 IntegrityErrorがサブクラス化されたSQLAlchemyのDBAPIError、の文書で

、それは例外が単に基礎となるデータベースAPIのエラーのため、元のエラーは例外でorigとして保存されているラッパーであることを説明しています。案の定、私はきれいに整理タプルを取得e.orig.argsを呼び出す:

を(1062年、「キーの 『名前』のための重複エントリ 『foobarに」』)私の知る限りでは

+0

はい、それは非常に便利です。 Thxそれは私にそれを掘る時間を節約するために。 –

0

、唯一の方法があります例外のエラー文字列を解析します。私はエラーを指定したタプル、違反した一意性制約と値を別々に持つ列を見つけることができません。

具体的には、部分文字列検索演算子または正規表現を使用して例外メッセージを検索できます。たとえば:

db.session.add(SupplierUser(supplier_id=supplier_id, username=username, password=password, creator=user)) 
    try: 
     db.session.commit() 
    except IntegrityError as err: 
     db.session.rollback() 
     if "UNIQUE constraint failed: user.username" in str(err): 
      return False, "error, username already exists (%s)" % username 
     elif "FOREIGN KEY constraint failed" in str(err): 
      return False, "supplier does not exist" 
     else: 
      return False, "unknown error adding user" 

はしかし、これらの文字列は、例えば、かなり長いSQL文が含まれているためであることができます。

(sqlite3.IntegrityError) UNIQUE constraint failed: user.username [SQL: 'INSERT INTO user (username, password_hash, created_time, creator_id, role, is_active, supplier_id) VALUES (?, ?, ?, ?, ?, ?, ?)'] [parameters: ('bob', ... 

したがって、あなたはを通して検索した場合、例外を解析するレイテンシをハンドリングエラーを最小限に抑えることができますsqlalchemyからの追加情報なしで、データベース・エラー・メッセージ。これは誤りを調べることによって行うことができます。小さくなければならない引数、:

'(sqlite3.IntegrityError) UNIQUE constraint failed: supplier_user.username',) 

更新例:

db.session.add(SupplierUser(supplier_id=supplier_id, username=username, password=password, creator=user)) 
    try: 
     db.session.commit() 
    except IntegrityError as err: 
     db.session.rollback() 
     err_msg = err.args[0] 
     if "UNIQUE constraint failed: supplier_user.username" in err_msg: 
      return False, "error, supplier username already exists (%s)" % username 
     elif "FOREIGN KEY constraint failed" in err_msg: 
      return False, "supplier does not exist" 
     else: 
      return False, "unknown error adding user" 

は、私がここで使用されるエラー構文はsqlite3のためであることに注意してください。

(1062, "Duplicate entry 'usr544' for key 'username'") 

適切な正規表現で実行できます。これはタプルのように見えますが、実際は文字列です(sqlalchemyバージョン1.1.3およびmysql 5.5)。例えば

except IntegrityError as err: 
     db.session.rollback() 
     if re.match("(.*)Duplicate entry(.*)for key 'username'(.*)", err.args[0]): 
    .... etc .... 
関連する問題