Question

J'ai un problème simple dans SQLAlchemy. J'ai un modèle dans une table, appelons-le Model1 ici. Je souhaite ajouter une ligne dans cette table et obtenir la clé auto-incrémentée afin de pouvoir créer un autre modèle avec elle et utiliser cette clé. Ce n'est pas une conception de base de données défectueuse (relation 1: 1, etc.). J'ai simplement besoin de cette clé dans une autre table, car l'autre est en cours de transfert sur un hôte distant, et j'ai besoin des clés correspondantes pour que les serveurs se comprennent. Il n'y aura plus de référence locale entre ces deux tables, et il est également impossible de créer des relations à cause de cela.

Considérez le code suivant:

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

Je souhaitais ne même pas être obligé de commettre "manuellement". En gros, ce que je voudrais réaliser, c’est: "Modèle1" est en croissance constante, avec la clé primaire Model.id croissante. AnotherModel n'est toujours qu'une petite fraction de Model1, qui n'a pas encore été traité. Bien sûr, je pouvais ajouter un drapeau dans "Modèle1", un champ booléen dans le tableau pour marquer les éléments déjà traités, mais j’espérais que cela ne serait pas nécessaire.

Comment puis-je faire fonctionner mon code ci-dessus?

Greets,

Tom

Était-ce utile?

La solution

Quelques choses:

  • Pourriez-vous expliquer en quoi la variable transaction est liée?
  • Exactement quelle instruction soulève l'UnboundExecutionError?
  • Veuillez fournir le message complet d'exception, y compris le suivi de la pile.
  • La chose "normale" à faire dans ce cas serait d'appeler DBSession.flush () . Avez-vous essayé cela?

Exemple:

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

object2 = AnotherModel(object1.id)

Pour une bonne explication de la session SA et de ce que flush () fait, voir Utilisation de la session .

Fondamentalement, flush () fait en sorte que les instances en attente deviennent persistantes, ce qui signifie que les nouveaux objets sont insérés dans les tables de la base de données. flush () met également à jour les tables avec les valeurs pour les instances suivies par la session et modifiées

commit () émet toujours flush () en premier.

Dans une transaction, vous pouvez vider plusieurs fois. Chaque flush () provoque des UPDATE et / ou des INSERT dans la base de données. L'ensemble de la transaction peut être validée ou annulée.

Autres conseils

si vous souhaitez générer de nouveaux identifiants de clé primaire sans rien valider, appelez simplement session.flush (). Cela émettra tout ce qui est en attente dans la base de données dans la transaction en cours.

Je ne l'ai utilisé qu'avec ForeignKeys, de sorte que dans le second cas, vous feriez plutôt model.AnotherModel (model1 = object1), puis cela a fonctionné (tm). Donc, je suppose que cela pourrait être un problème avec vos modèles, alors vous pourriez peut-être les poster aussi?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top