4

私はフラスコアプリを持っていて、そこではすべて互いに関係のあるクラスをたくさん作りました:

ユーザーコース講義ノートキューアセット

それで、私は新しい講義とメモを作ろうとしています、そして私はそれぞれのために定義された方法を持っています。

メモを作成

def createPad(user,course,lecture):
    lecture.queues.first().users.append(user)
    # make new etherpad for user to wait in
    newNote = Note(dt) # init also creates a new pad at /p/groupID$noteID
    db.session.add(newNote)
    #db.session.commit()

    # add note to user, course, and lecture
    user.notes.append(newNote)
    course.notes.append(newNote)
    lecture.notes.append(newNote)
    db.session.commit()

return newNote

createLecture

def createLecture(user, course):
    # create new lecture
    now = datetime.now()
    dt = now.strftime("%Y-%m-%d-%H-%M")
    newLecture = Lecture(dt)
    db.session.add(newLecture)

    # add lecture to course, add new queue to lecture, add user to queue, add new user to lecture
    course.lectures.append(newLecture)
    newQueue = MatchQueue('neutral')
    db.session.add(newQueue)
    newLecture.users.append(user)


    # hook up the new queue to the user, lecture
    newQueue.users.append(user)
    newQueue.lecture = newLecture
    # put new lecture in correct course
    db.session.commit()

    newLecture.groupID = pad.createGroupIfNotExistsFor(newLecture.course.name+dt)['groupID']

    db.session.commit()
    return newLecture

これはすべて、いくつかのコントローラーロジックから呼び出されます

newlec = createLecture(user, courseobj)

# make new pad
newNote = createPad(user,courseobj,newlec)

# make lecture live
newLecture.live = True
db.session.commit()

redirect(somewhere)

これにより、次のエラーがスローされます。

ObjectDereferencedError:属性'Queue.users'の変更イベントを発行できません-タイプの親オブジェクトがガベージコレクションされました。

lecture.queues.first().users.append(user)createPad。_

これが何を意味するのか私にはわかりません。私はここでsqlalchemyの基本的な知識が不足していると思います(私はsqlalchemy noobです)。どうしたの?

4

2 に答える 2

12
lecture.queues.first().users.append(user)

その意味は:

first()メソッドはデータベースにアクセスしてオブジェクトを生成します。私はあなたのマッピングをフォローしていませんが、それはQueueオブジェクトだと思います。

次に、キューの「users」コレクションにアクセスします。

この時点で、Python自体がキューをガベージ収集します。「users」が返されると、キューはどこにも参照されません。これが、参照カウントのガベージコレクションの仕組みです。

次に、「users」を「users」に追加しようとします。SQLAlchemyは、マップされたすべての属性への変更を追跡するQueue.name = "some name"必要があります。つまり、SQLAlchemyはそれを親Queueオブジェクトに登録して、フラッシュすることを認識させる必要があります。あなたが言うならQueue.users.append(someuser)、同じ考え、それは親に変更イベントを登録する必要があります。

QueueSQLAlchemyは、がなくなったため、これを行うことができません。したがって、メッセージが発生します。SQLAlchemyはここで親に対してweakrefを持っているので、何が起こったのかを正確に知っています(そして、オブジェクトモデルで不要な参照サイクルを作成すると人々が非常に動揺するため、それを防ぐことはできません)。

解決策は非常に簡単で、クエリ結果を変数に割り当てることも読みやすくなっています。

queue = lecture.queues.first()
queue.users.append(user)
于 2013-01-16T14:32:21.120 に答える
0

私はたくさんのリファクタリングを行い、インスタンス化中にいくつかのオブジェクトに対応するオブジェクトを入れました。これにより、物事が非常にきれいになりました。どういうわけか問題はなくなりました。

私が別の方法で行ったことの1つは、多対多の関係で、backrefをdb.backref()に変更しました。

courses = db.relationship('Course', secondary=courseTable, backref=db.backref('users', lazy='dynamic'))
lectures = db.relationship('Lecture', secondary=lectureTable, backref=db.backref('users', lazy='dynamic'))
notes = db.relationship('Note', secondary=noteTable, backref=db.backref('users', lazy='dynamic'))
queues = db.relationship('Queue', secondary=queueTable, backref=db.backref('users', lazy='dynamic'))
于 2013-01-16T04:20:50.150 に答える