SQLAlchemy: ¿Se han perdido las asignaciones de objetos después de la confirmación?

StackOverflow https://stackoverflow.com/questions/1033199

  •  06-07-2019
  •  | 
  •  

Pregunta

Tengo un problema simple en SQLAlchemy. Tengo un modelo en una tabla, llamémoslo Model1 aquí. Quiero agregar una fila en esta tabla y obtener la clave autoincrementada, para poder crear otro modelo con ella y usar esta clave. Este no es un diseño de base de datos defectuoso (relación 1: 1, etc.). Simplemente necesito esta clave en otra tabla, porque la otra tabla se está transfiriendo a un host remoto, y necesito las claves coincidentes para que los servidores se entiendan entre sí. No habrá más referencias locales entre estas 2 tablas, y tampoco es posible crear relaciones debido a eso.

Considere el siguiente código:

object1 = model.Model1(param)
DBSession.add(object1)

# if I do this, the line below fails with an UnboundExecutionError.
# and if I dont do this, object1.id won't be set yet
#transaction.commit()

object2 = model.AnotherModel(object1.id) #id holds the primary, autoincremented key

Desearía no tener que comprometerme "manualmente". Básicamente, lo que me gustaría lograr es "Modelo1". está en constante crecimiento, con el aumento de la clave primaria Model.id. AnotherModel siempre es solo una pequeña fracción de Model1, que aún no se ha procesado. Por supuesto, podría agregar un indicador en "Modelo1", un campo booleano en la tabla para marcar elementos ya procesados, pero esperaba que esto no fuera necesario.

¿Cómo puedo hacer que funcione mi código anterior?

Saludos,

Tom

¿Fue útil?

Solución

Un par de cosas:

  • ¿Podría explicar a qué está vinculada la variable transacción ?
  • ¿Exactamente qué afirmación genera el UnboundExecutionError?
  • Proporcione el mensaje de excepción completo, incluido el seguimiento de la pila.
  • Lo 'normal' en este caso sería llamar a DBSession.flush () . ¿Has probado eso?

Ejemplo:

object1 = Model1(param)
DBSession.add(object1)
DBSession.flush()
assert object1.id != None # flushing the session populates the id

object2 = AnotherModel(object1.id)

Para obtener una excelente explicación de la sesión de SA y lo que hace flush () , consulte Uso de la sesión .

Básicamente, flush () hace que las instancias pendientes se vuelvan persistentes, lo que significa que se insertan nuevos objetos en las tablas de la base de datos. flush () también ACTUALIZA las tablas con valores para instancias que la sesión rastrea que tiene cambios.

commit () siempre emite flush () primero.

Dentro de una transacción, puede vaciar varias veces. Cada descarga () genera ACTUALIZACIONES y / o INSERTAS en la base de datos. Toda la transacción puede confirmarse o revertirse.

Otros consejos

si desea obtener nuevos identificadores de clave primaria para generar sin comprometer nada, simplemente llame a session.flush (). Eso emitirá todo lo pendiente de la base de datos dentro de la transacción actual.

Solo he usado esto con ForeignKeys, por lo que en el segundo caso preferirías hacer model.AnotherModel (model1 = object1), y luego simplemente funcionó (tm). Por lo tanto, sospecho que esto puede ser un problema con sus modelos, ¿tal vez podría publicarlos también?

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