2011-03-16 2 views
0

PySide (PyQt)에서 SQLAlchemy를 사용하는 데 문제가 있습니다. 나는 팝업하는 QtGui.QDialog 노력하고있어,하지만 난 할 때이 SQLAlchemy의 예외를 throw :SQLAlchemy IntegrityError

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 데이터 모델이 데이터베이스를 많이 쿼리하고 있다는 것입니다. 그냥 그 팝업이 때 QDialog (어떤 코드를 일부 테이블 열을 쿼리 할 수 ​​있음)이 오류가 throw됩니다 것 같습니다. 이상하게도 이것은 일관성이 없습니다. 예외가 발생하기 전에 팝업이 먼저 나타나기도하고 예외 뒤에 팝업이 나타나는 경우가 있습니다. 정상적인 상황 QTableView 데이터 모델은 작동 좋은, 그냥 나는이 대화 상자를 팝업 (그리고 아이러니하게도, 팝업은 전혀 등 QLineEdit,은 QTextEdit, 같은 단지 표준 위젯 어떤 QTableView를 사용하지 않는)

그것은 만약을 때 도와 드리겠습니다. 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

select 문은 아무 작업도 수행하지 않았지만 쿼리 전에 세션에 문제가 발생했을 수 있습니다. 쿼리가 실행되면 변경 사항이 플러시됩니다 (예 : 사용자 삽입). "dbviewandmodel.py"파일의 나머지 부분을 볼 수 있습니까? –

+0

나는이 상황이 발생했을 때 (어떤 데이터도 삽입하지 않고 데이터베이스의 데이터를 수정하지 않고) 데이터를 쿼리하는 경우에도 모든 종류의 데이터베이스 수정 작업을 수행하지 않았습니다. 나는이 충돌이 일어나지 않는 방법을 발견했다고 생각한다. (실제로는 수정이 아니라, 더 구체적으로 뭔가 특별한 일을하지 않음으로써 일어날 수있다.) 조금 길어질수록 답변을 추가 할 것입니다. – Raceyman

답변

0

나는이 문제를 해결할 수 있었지만 SQLAlchemy가 내 데이터베이스에 행을 삽입하려고하는 이유를 여전히 분명하게 알지 못합니다. 정말 저를 괴롭히지 만 더 이상 발생하지 않습니다. 내 코드 I에서

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$'} 

: 하여간

, 무슨, 생각, 일이, 내 SQLAlchemy의 데이터 모델과 내가 접근 한 방식과 관련이 여기에 해당 모델의 조각이다 GUI에서 하드 코드를 작성하지 않고 GUI의 '예쁜'레이블 이름을 얻는 방법이 필요했습니다. GUI 양식을 만드는 동적 방법을 만들려고 시도했습니다. 그래서, 데이터 모델에 'prettyname'메소드를 추가하여 해당 데이터 모델에 특정 애플리케이션 메타 데이터를 제공했습니다. 내가하는 모든 일은 사전 항목을 반환하는 것뿐입니다.

때때로이 데이터를 사용자의 클래스 인스턴스에서 가져오고 경우에 따라 Users의 쿼리 결과 (예 : Users.get_by (id = 1))에서 가져와야한다는 2 차적인 문제가있었습니다. 결과적으로이 데이터를 가져 오는 작업은 두 가지 방식으로 수행되어야했습니다. 클래스 인스턴스에서 나는 값이 방법으로 얻어야했다 :

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

을하지만 쿼리를 사용하여 때 그것이 결과 :

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

SQLAlchemy의 내가 이전 사용하던 진짜 문제가있는 것 메서드 (클래스 인스턴스 메서드) -이 때마다 내가 충돌을보고 사용되었습니다. 후자의 인스턴스를 사용할 때 나는 결코 충돌을 보지 못했습니다.그래도 클래스 인스턴스에서 해당 메타 데이터에 액세스해야했습니다.

해결 방법 또는 다른 Stackoverflow 문서에서 나온 문제를 해결하기 위해 무엇을 말 했어야합니까? (Stackoverflow에서 모두 감사합니다 - 나는 당신 없이는 없을 것입니다). 내가 클래스 인스턴스 찾고 있어요 경우

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) 

이 날에 관계없이 정보 인수에 사전 데이터를 얻을 수 반성의 일반적인 방법을 사용할 수 있습니다, 또는 쿼리 결과 : 나는 dbmodel의 구조를 변경 . 이 경우 클래스 또는 쿼리 결과의 '.table'메서드를 사용하고 필요한 열 (.c)을 얻은 다음 해당 열의 .info 메서드를 사용하여 사전을 반환합니다.

SQLAlchemy는 더 이상 임의로 데이터베이스에 행을 삽입하려고하지 않습니다.

+0

문제를 일으키는 정확한 코드를 게시 한 적이 없으므로이 사실을 확신 할 수 없습니다. 그러나 위의 스 니펫은'prettyname = Users(). prettyname() [ 'username']'을 읽습니다. Elixer를 사용하기 때문에이 줄을 사용하면 users 테이블에 쓸 수 있습니다. 'Users()'는 새로운 Users 인스턴스를 생성합니다. Elixer는 이것을 세션에 추가 할 것입니다. 이 호출 후에 수행 된 쿼리는 새 Users 인스턴스를 커밋하려고 시도합니다. 따라서이 스 니펫이 코드에 있으면 사용자 테이블에 삽입하는 것이 올바른 동작이었을 것입니다. –

+0

특히 코드에서 문제가 발생하는 위치를 확실히 말할 수 없다는 점에서 의미가 있습니다. 그 코드 라인은 내가 문제가 될 수있는 곳에 가까이 갈 수 있었다. 이 방법으로 Users() 구문을 사용하지 않으려 고 노력할 것입니다. 감사! – Raceyman