I post the detail class here:
Session = scoped_session(sessionmaker())
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
question_count = Column(Integer)
questions = relationship('Question', backref='user',
primaryjoin='User.id==Question.user_id')
class QuestionCallback(MapperExtension):
def after_insert(self, mapper, connection, instance):
user = instance.user
user.question_count += 1
class Question(Base):
__tablename__ = 'questions'
id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
user_id = Column(Integer, ForeignKey('users.id'))
Now, a user post a new question, after the question has been inserted
to database, the 'user.question_count' should be updated too.
# load user
question = Question(title='aa', content='bb', user_id=user_id)
Session.add(question)
Session.commit()
What I want is: the question is added to database, and after inserted,
the user of this question should have its 'question_count' column
updated too.
I think the extension should be on the Question class. Because the
flow is:
Insert a question first, then update the associated user. If I write
'before_insert()' on user, it won't have chance to be invoked.
On 9月6日, 上午2时05分, Michael Bayer <[email protected]> wrote:
> On Sep 5, 2010, at 1:27 PM, Freewind wrote:
>
>
>
>
>
> > There are two classes: User and Question
>
> > A user may have many questions, and it also contains a question_count
> > to record the the count of questions belong to him.
>
> > So, when I add a new question, I want update the question_count of the
> > user. At first, I do as:
>
> > question = Question(title='aaa', content='bbb')
> > Session.add(question)
> > Session.flush()
>
> > user = question.user
> > ### user is not None
> > user.question_count += 1
> > Session.commit()
>
> > Everything goes well.
>
> > But I wan't to use event callback to do the same thing. As following:
>
> > from sqlalchemy.orm.interfaces import MapperExtension
> > class Callback(MapperExtension):
> > def after_insert(self, mapper, connection, instance):
> > user = instance.user
> > ### user is None !!!
> > user.question_count += 1
>
> Not really sure why question.user would be None here if you had set it (in
> your example above, its not set, unless you have some odd join condition
> going on), but it would also be more appropriate here for the extension to be
> on the User class, not Question, using before_insert().
>
>
>
> > 2. If I change that line to:
>
> > Session.query(User).filter_by(id=instance.user_id).one()
>
> > I can get the user successfully, But: the user can't be updated!
>
> > Look I have modified the user:
>
> > user.question_count += 1
>
> > But there is no 'update' sql printed in the console, and the
> > 'question_count' are not updated.
>
> So, if you were to emit the INSERT statements for both your User and your
> Question, assuming Question has a foreign key to User, which would INSERT
> would need to occur first ? The "User" row would already have been inserted
> here by the time your Question after_insert is invoked (and the fact that you
> can look it up proves it). People usually use before_insert() which states
> in its doc that you can't manipulate the flush plan or assume it will change
> in any way at that point, but I guess I'll make this message much more
> explicit for all the intra-flush() hooks.
>
>
>
> > 3. I try to add 'Session.flush()' or 'Session.commit()' in the
> > 'after_insert()' method, but both cause errors.
>
> The error should be clear here - "Session is already flushing". The
> extension points are within a transaction, within a flush. Invoking
> flush() within flush() is not something that is possible, and invoking
> commit() within flush(), assuming the reentrant flush() issue weren't
> present, would mean half of the flush is committed, half not, and the
> transaction would then be incorrectly committed before it was actually
> committed on the outside.- 隐藏被引用文字 -
>
> - 显示引用的文字 -
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.