Python SQLAlchemy IntegrityError

Python SQLAlchemy IntegrityError,python,sqlalchemy,pyqt,pyside,python-elixir,Python,Sqlalchemy,Pyqt,Pyside,Python Elixir,我在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:\P

我在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
model/view,并且该模型中没有
insertRows
函数)

我不知道发生了什么,也不知道如何解决它——再说一遍,我根本没有修改SQL记录的代码,但SQLAlchemy仍然试图将空白记录插入到我的一个SQL表中。在后台,我所能看到的是
QTableView
数据模型正在大量查询数据库。似乎当我弹出这个
QDialog
(里面确实有一些查询表列的代码)时,就会抛出这个错误。奇怪的是,这并不一致,有时弹出窗口出现在异常之前,有时弹出窗口出现在异常之后。在正常情况下,
QTableView
数据模型工作得很好,只是当我弹出这个对话框时就不行了(讽刺的是,弹出窗口根本没有使用任何
QTableView
,只使用标准的小部件,如QLineEdit、qtexedit等)

如果有帮助的话,我将使用Python2.7和SQLAlchemy 0.6.6(以及Elixir 0.7.1)以及PySide 1.0.0(以及PyQt4.8.3)。我在Windows7上使用SQL2008R2(Express)。是的,我试着重新启动电脑,但问题仍然发生在重新启动后。我不愿意发布更多的代码,因为我在这个特定的项目中有很多代码,而且我无法确定问题的具体细节


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

我已经设法解决了这个问题,但我仍然不太清楚为什么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$'}
但当我使用查询结果时,它是:

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)
类用户(实体):
使用_选项(tablename='users')
username=Field(字符串(50),unique=True,info={'prettyname':'User Name})
全名=字段(字符串(255),信息={'prettyname':'Full Name'})
email=字段(字符串(255),信息={'prettyname':'email Address'})
passwordmd5=字段(字符串(32),信息={'hidden':True})
定义报告(自我):
返回“”。格式(self.username、self.fullname、self.email)
这允许我使用一种常见的内省方法来获取info参数中的字典数据,而不管我是在查看类实例还是查询结果。在本例中,我使用类或查询结果的“.table”方法,然后获取所需的列(.c),然后使用该列的.info方法返回字典


不管是什么情况,现在SQLAlchemy不再试图在数据库中任意插入行。

select语句可能没有做任何事情,但查询之前的会话可能发生了一些事情。当查询运行时,它将刷新仍要进行的任何更改(例如插入用户)。我们可以看到“dbviewandmodel.py”文件的其余部分吗?发生这种情况时,我仍然没有做任何类型的数据库修改(没有插入,没有对数据库中的任何数据进行编辑),只是查询数据。我想我已经找到了一种避免崩溃发生的方法(不是真正的修复,更像是,我可以通过不做特定的事情来避免崩溃发生)。我将添加一个答案,因为它有点冗长。由于您从未发布导致问题的确切代码,我不能确定这一点。但是,上面有一个代码片段,内容是
prettyname=Users().prettyname()['username']
。由于使用Elixer,此行可能会导致对users表的写入<代码>用户()将创建一个新的用户实例。Elixer将把它添加到会话中。在此调用之后执行的查询将尝试提交新用户实例。因此,如果您的代码中有此代码段,那么将其插入到users表中是正确的行为。这是有意义的,特别是考虑到我无法确定问题在代码中的何处发生。那一行代码是我能找到的最接近问题所在的地方。接下来,我将尝试避免以这种方式使用Users()构造。谢谢
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)