[Python-es] Pyramid + SQLAlchemy + commit() inoportuno
Miguel Sanchez
msanchez en uninet.edu
Dom Oct 9 07:50:56 EDT 2022
Hola Lista.
Estoy comenzando con Pyramid + SQLAlchemy y me he atascado.
Es posible que esté haciendo varias cosas mal al mismo tiempo. Les digo cómo lo estoy haciendo:
He definido los modelos, según la documentación recomienda (creo):
class Mitabla(Base):
__tablename__ = 'mitabla'
id = Column(Integer, primary_key=True)
dato1 = Column(Integer)
def __init__(self, dato1):
self.dato1 = dato1
def __setattr__(self, attr, valor):
if attr == 'dato1':
if not isinstance(int(valor), int):
raise ValueError('dato1 no es un int')
super().__setattr__(attr, valor)
Como pueden ver uso __setattr__ para filtrar los valores que se pueden asignar a las columnas.
He definido una "vista" que va a ser invocada desde un ajax y que espero me devuelva unos valores json:
@view_config(route_name='haceralgo',
http_cache=0,
renderer='json'
)
def haceralgo(request):
En dicha vista tengo varios executes a la sesion del request (request.dbsession)
Unos seleccionan datos, otras borran, otras actualizan
Esto funciona perfectamente, genero una respuesta json y los datos quedan modificados/borrados
try:
sentencia = select( ....
resultado = request.dbsession.execute(sentencia).scalar_one()
sentencia = delete( ....
request.dbsession.execute(sentencia)
sentencia = select( ...
resultado2 = request.dbsession.execute(sentencia).scalar_one()
resultado2.dato1 = 100
return Response(.....
except ....
El problema aparece cuando hay un error y quiero capturarlo .... por ejemplo haciendo que resultado2.dato1 = 'No sea un entero' o simplemente metiendo un 1/0 en el try ... except
Mi idea es capturar el error, loguearlo y enviar un json informando del error
Si hago:
except Exception as error:
request.dbsession.rollback()
log.debug(error)
raise
Todo funciona como debería salvo que no respondo a la petición ajax, lo que llega es un error generado por el servidor:
Internal Server Error
The server encountered an unexpected internal server error
(generated by waitress)
Si hago
except Exception as error:
log.debug(error)
return Response(json.dumps('Datos con el error'),
content_type='application/json; charset=utf-8',
status=500)
Se genera la respuesta json correctamente
PERO también se genera un commit() que hace que todas las sentencias del try: donde NO se han generado errores (del tipo que sea) se graben en la base de datos
Esto es un problema pues la bd se me queda en un estado inconsistente
Si hago
except Exception as error:
request.dbsession.rollback()
log.debug(error)
return Response(json.dumps('Datos con el error'),
content_type='application/json; charset=utf-8',
status=500)
En el servidor se lanza un error: sqlalchemy.exc.ResourceClosedError: This transaction is closed
No se genera la respuesta json
Y llega el mismo error de antes generado por el servidor
Internal Server Error
The server encountered an unexpected internal server error
(generated by waitress)
Alguna sugerencia???, que hago mal???
Gracias y saludos
Miguel Sánchez
Más información sobre la lista de distribución Python-es