2009-10-14 5 views
3

Je reçois l'erreur (probablement trivial), mais complètement désemparés sur les causes possibles. Je veux insérer deux objet dans la base de données en utilisant SQLAlchemy. Ces objets sont liés, voici les déclarations. Classe utilisateur:deux objets connexes Insertion échouent dans SQLAlchemy

class User(Base): 
    __tablename__ = 'cp_user' 

    id = Column(Integer, Sequence('id_seq'), primary_key=True) 
# ... more properties 

Photo de classe (l'utilisateur peut avoir beaucoup d'entre eux):

class Picture(Base): 
    __tablename__ = 'picture' 

    id = Column(Integer, Sequence('id_seq'), primary_key=True) 
    authorId = Column('author_id', Integer, ForeignKey('cp_user.id')) 
    author = relation(User, primaryjoin = authorId == User.id) 
# ... more properties 

J'essaie d'insérer la nouvelle image après que je l'ai allé chercher l'utilisateur depuis le DB, ou juste créée:

s = newSession() 
user = s.query(User.name).filter("...some filter here...").first() 
if not(user): 
    user = User() 
    s.add(user) 
    s.commit() 

picture = Picture() 
picture.author = user 
s.add(picture) 
s.commit() 

Cela échoue à l'exception: AttributeError: 'RowTuple' object has no attribute '_sa_instance_state'

J'ai essayé déplacer l'assignation de l'auteur au constructeur - même erreur. Je ne peux pas attribuer d'ID directement - cela casse l'idée d'ORM.

Qu'est-ce que je fais de mal?

Répondre

5

Votre code échoue si la branche not(user) ne sont pas prises.

Vous User.name requête qui est une colonne et non un objet lié.

user = s.query(User).filter("...some filter here...").first() 

Un objet obtient son identifiant dès qu'il est transmis à la base de données. Vous faites cela dans la branche avec un commit. Ce n'est probablement pas ce que vous voulez. Vous devriez émettre une couleur. Lisez les documents sur la différence.

Aussi, vous ne devriez pas avoir à engager l'utilisateur nouvellement créé. Si vous affectez un objet utilisateur à une relation, celle-ci doit être gérée de manière transparente. commettras Chaque ferme une transaction, ce qui peut être très coûteux (verrouillage, disque cherche, etc)

+0

Merci, en remplacement User.name avec l'utilisateur a aidé! Je pensais que je suis devenu fou, mais maintenant ça marche :) –