Pregunta

Tengo problemas para usar Sqlalchemy con Pyside (PYQT). Estoy tratando de aparecer un QtGui.QDialog, pero cuando hago esta Sqlalchemy lanza una excepción:

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)

Esto es particularmente preocupante porque no tengo código, en ningún lado, que incluso intenta insertar registros en SQL; Solo estoy intentando consultar los datos de la base de datos. De hecho, mi modelo DB es de solo lectura con respecto a lo que está haciendo Pyside/Pyqt (es decir, estoy usando un QtGui.QTableView modelo/vista y no hay insertRows función en ese modelo).

No tengo idea de lo que está pasando o cómo resolverlo; nuevamente, no tengo código para modificar los registros SQL, pero aún así SQLalchemy intenta insertar registros en blanco en una de mis tablas SQL. Todo lo que puedo ver, en el fondo, es el QTableView El modelo de datos consulta mucho la base de datos. Simplemente parece que cuando aparezco esto QDialog (que tiene algún código para consultar alguna columna de tabla) Este error se lanza. Curiosamente, esto no es consistente, en algún momento la ventana emergente aparece primero antes de la excepción, a veces la ventana emergente aparece después de la excepción. En circunstancias normales, el QTableView El modelo de datos funciona muy bien, pero no cuando emergo este diálogo (e irónicamente, la ventana emergente no está utilizando ninguna QTableView En absoluto, solo widgets estándar como Qlineedit, QTextedit, etc.)

Si ayuda, estoy usando Python 2.7 con Sqlalchemy 0.6.6 (también con Elixir 0.7.1) y Pyside 1.0.0 (y Pyqt4 4.8.3). Estoy en Windows 7 usando SQL 2008 R2 (Express). Y sí, he intentado reiniciar la PC, pero el problema aún ocurre después de un reinicio. Soy reacio a publicar más código porque tengo mucho en este proyecto en particular y no puedo obtener el problema de nada específico.

Espero que alguien sepa las rarezas en Sqlalchemy y/o Pyqt que podrían estar relacionadas con esto. También espero poder continuar usando Sqlalchemy, ya que tengo un modelo de datos grande construido; Soy reacio, en este momento, a abandonar esto y usar las características SQL de Pyqt.

¿Fue útil?

Solución

He logrado hacer que este problema desaparezca, pero todavía no me queda claro por qué Sqlalchemy estaba tratando de insertar filas en mi base de datos, eso realmente me molesta, pero ya no está sucediendo.

En cualquier caso, lo que estaba sucediendo, estaba relacionado con mi modelo de datos de Sqlalchemy y la forma en que estaba accediendo a él, aquí hay un fragmento de ese modelo:

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

En mi código necesitaba una forma de obtener nombres de etiquetas 'bonitas' para una GUI sin tener que codificar esto en una GUI (he estado tratando de crear una forma dinámica de construir formularios de GUI). Entonces, agregué el método 'PrettyName' a mi modelo de datos para darme algunos metadatos específicos de la aplicación en ese modelo de datos. Todo lo que estoy haciendo es devolver un diccionario de artículos.

Tenía un problema secundario en que a veces necesitaba obtener estos datos de la instancia de clase para los usuarios y, a veces, para un resultado de consulta para los usuarios (por ejemplo, usuarios.get_by (id = 1)). Al final resultó que, recuperar estos datos debía hacerse de dos maneras. En los casos de clase tuve que obtener el valor de esta manera:

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

Pero cuando estaba usando los resultados de la consulta, era:

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

Sqlalchemy parece tener un problema real cuando estaba usando el método anterior (el método de instancia de clase), ya que esto se usaba cada vez que estaba viendo el bloqueo. Cuando estaba usando la última instancia, nunca estaba viendo un bloqueo. Aún así, necesitaba acceso a esos metadatos en la instancia de clase.

La solución, o debería decir lo que resultó arreglar esto, provino de otro artículo de Stackoverflow (gracias a todos en Stackoverflow, no sería nada sin usted). Cambié la estructura del 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)

Esto me permite usar un método común de introspección para obtener los datos del diccionario en el argumento de información, independientemente de si estoy mirando una instancia de clase o un resultado de la consulta. En este caso, uso el método '.table' del resultado de la clase o consulta, luego obtengo la columna que necesito (.c), luego uso el método .info de esa columna para devolver el diccionario.

Cualquiera sea el caso, ahora Sqlalchemy ya no intenta insertar arbitrariamente filas en la base de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top