0

PySide(PyQt) で SQLAlchemy を使用すると問題が発生します。をポップアップしようとしてQtGui.QDialogいますが、これを行うと SQLAlchemy が例外をスローします。

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\preo\preodb\dbviewandmodel.py", line 32, in rowCount
    return len(self.rows())    
  File "C:\Python27\lib\site-packages\preo\preodb\dbviewandmodel.py", line 30, in rows
    return self.tableobj.query.all()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\query.py", line 1579, in all
return list(self)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\query.py", line 1688, in __iter__
    self.session._autoflush()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 862, in _autoflush
    self.flush()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 1388, in flush
    self._flush(objects)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 1469, in _flush
    flush_context.execute()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\unitofwork.py", line 302, in execute
    rec.execute(self)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\unitofwork.py", line 446, in execute
    uow
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\mapper.py", line 1878, in _save_obj
    execute(statement, params)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1191, in execute
    params)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1271, in _execute_clauseelement
    return self.__execute_context(context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1302, in __execute_context
    context.parameters[0], context=context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1401, in _cursor_execute
    context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1394, in _cursor_execute
    context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\default.py", line 299, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (IntegrityError) ('23000', "[23000] [Microsoft][ODBC
SQL Server Driver][SQL Server]Violation of UNIQUE KEY
constraint 'UQ__users__F3DBC5720DAF0CB0'. Cannot insert duplicate key in
object 'dbo.users'. (2627) (SQLExecDirectW); [01000] [Microsoft][ODBC SQL Server
Driver][SQL Server]The statement has been terminated. (3621)") u'INSERT INTO users
(username, fullname, email, passwordmd5) OUTPUT inserted.id VALUES (?, ?, ?, ?)'
(None, None, None, None)

SQL にレコードを挿入しようとするコードがどこにもないため、これは特に厄介です。データベースからデータをクエリしようとしているだけです。実際、私の DB モデルは、PySide/PyQt が行っていることに関して読み取り専用です (つまり、QtGui.QTableViewモデル/ビューを使用していinsertRowsて、そのモデルには機能がありません)。

何が起こっているのか、それを解決する方法がわかりません - 繰り返しますが、SQL レコードを変更するコードはまったくありませんが、SQLAlchemy は SQL テーブルの 1 つに空白のレコードを挿入しようとします。バックグラウンドで確認できるのは、QTableViewデータ モデルがデータベースに対して多くのクエリを実行していることだけです。これをポップアップするとQDialog(テーブル列をクエリするためのコードが含まれている)、このエラーがスローされるようです。奇妙なことに、これは一貫していません。例外の前にポップアップが最初に表示される場合もあれば、例外の後にポップアップが表示される場合もあります。通常の状況では、QTableViewデータ モデルはうまく機能しますが、このダイアログをポップアップするときは例外です (皮肉なことに、ポップアップはQTableViewQLineEdit、QTextEdit などの標準ウィジェットだけを使用しており、何も使用していません)。

それが役立つ場合は、SQLAlchemy 0.6.6 (Elixir 0.7.1 も) と PySide 1.0.0 (および PyQt4 4.8.3) で Python 2.7 を使用しています。SQL 2008 R2 (Express) を使用して Windows 7 を使用しています。はい、PC を再起動してみましたが、再起動後も問題が発生します。この特定のプロジェクトには多くのコードがあり、特定の問題を突き止めることができないため、これ以上コードを投稿するのは気が進まない。

これに関連する可能性のある SQLAlchemy や PyQt の奇妙な点を誰かが知っていることを願っています。また、大規模なデータ モデルを構築しているため、SQLAlchemy を引き続き使用できることを願っています。現時点では、これを放棄して PyQt の SQL 機能を使用するのは気が進まない。

4

1 に答える 1

0

私はなんとかこの問題を解決することができましたが、SQLAlchemyがデータベースに行を挿入しようとした理由はまだはっきりしていません-それは本当に私を悩ませますが、それはもう起こりません。

とにかく、起こったことは、私のSQLAlchemyデータモデルとそれにアクセスする方法に関連していたと思います。これがそのモデルのスニペットです。

from elixir import *

metadata.bind = 'mssql+pyodbc://username:password/dbname'
metadata.bind.echo = False

class Users(Entity):
    using_options(tablename = 'users')
    username = Field(String(50), unique=True)
    fullname = Field(String(255))
    email = Field(String(255))
    passwordmd5 = Field(String(32))
    def __repr__(self):
        return "<Users ({})({})({})>".format(self.username, self.fullname, self.email)
    def prettyname(self):
        return {'username':'User Name', 'fullname':'Full Name', 'email':'Email Address', 'passwordmd5':'$hidden$'}

私のコードでは、GUIでこれをハードコーディングすることなく、GUIの「きれいな」ラベル名を取得する方法が必要でした(GUIフォームを構築する動的な方法を作成しようとしてきました)。そこで、データモデルに「prettyname」メソッドを追加して、そのデータモデルにアプリケーション固有のメタデータを追加しました。私がしているのは、アイテムの辞書を返すことだけです。

ユーザーのクラスインスタンスからこのデータを取得する必要がある場合と、ユーザーのクエリ結果(たとえば、Users.get_by(id = 1))の場合があるという、二次的な問題がありました。結局のところ、このデータの取得は2つの方法で行う必要がありました。クラスインスタンスでは、次の方法で値を取得する必要がありました。

prettyname = Users().prettyname()['username']

しかし、クエリ結果を使用していたときは、次のようになりました。

prettyname = queryresult.prettyname()['username']

SQLAlchemyは、前者のメソッド(クラスインスタンスメソッド)を使用していたときに実際の問題を抱えているようです。これは、クラッシュが発生するたびに使用されていたためです。後者のインスタンスを使用していたとき、クラッシュは発生しませんでした。それでも、クラスインスタンスでそのメタデータにアクセスする必要がありました。

修正、またはこれを修正するために判明したことは、別のStackoverflowの記事から来ました(Stackoverflowの皆さんに感謝します-私はあなたなしでは何もありません)。dbmodelの構造を変更しました:

class Users(Entity):
    using_options(tablename = 'users')
    username = Field(String(50), unique=True, info={'prettyname':'User Name'})
    fullname = Field(String(255), info={'prettyname':'Full Name'})
    email = Field(String(255), info={'prettyname':'Email Address'})
    passwordmd5 = Field(String(32), info={'hidden':True})
    def __repr__(self):
        return "<Users ({})({})({})>".format(self.username, self.fullname, self.email)

これにより、クラスインスタンスを表示しているか、クエリ結果を表示しているかに関係なく、一般的なイントロスペクションの方法を使用して、info引数のディクショナリデータを取得できます。この場合、クラスまたはクエリ結果の「.table」メソッドを使用してから、必要な列(.c)を取得し、その列の.infoメソッドを使用して辞書を返します。

いずれにせよ、SQLAlchemyはデータベースに行を任意に挿入しようとしなくなりました。

于 2011-03-17T15:00:29.903 に答える