SQLAlchemy IntegrityError

时间:2011-03-16 23:45:38

标签: python sqlalchemy pyqt pyside python-elixir

我在使用SQLAlchemy和PySide(PyQt)时遇到问题。我正在尝试弹出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表中。我在后台看到的是QTableView数据模型正在查询数据库A LOT。看来,当我弹出这个QDialog(其中有一些代码来查询某些表列)时,会抛出此错误。奇怪的是,这并不一致,有时弹出窗口会在异常之前出现,有时弹出窗口会出现在异常之后。在正常情况下,QTableView数据模型工作得很好,而不是当我弹出这个对话框时(具有讽刺意味的是,弹出窗口根本没有使用任何QTableView,只是标准的小部件,如QLineEdit,QTextEdit等) 。)

如果有帮助,我使用Python 2.7和SQLAlchemy 0.6.6(也使用Elixir 0.7.1)和PySide 1.0.0(以及PyQt4 4.8.3)。我在Windows 7上使用SQL 2008 R2(Express)。是的,我尝试重新启动PC,但重启后问题仍然存在。我不愿意发布更多代码,因为我在这个特定的项目中有很多代码而且我无法确定任何具体的问题。

我希望有人可能知道SQLAlchemy和/或PyQt中可能与此有关的奇怪之处。我也希望我可以继续使用SQLAlchemy,因为我已经构建了一个大型数据模型;在这一点上,我不愿放弃这个并使用PyQt的SQL功能。

1 个答案:

答案 0 :(得分: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))。事实证明,检索这些数据必须以两种方式完成。在类实例中,我必须以这种方式获得值:

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不再试图在数据库中随意插入行。