sqlalchemy:ObjectdereferencedError

Oli*_*ver 3 python database sqlalchemy flask

我有一个烧瓶应用程序,我做了一堆所有关系相互关联的类:

用户课程讲义笔记队列资产

所以我正在尝试做一个新的讲座和笔记,我为每件事都定义了一个方法.

创建注释

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这是从一些控制器逻辑调用的

newlec = createLecture(user, courseobj)

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

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

redirect(somewhere)
Run Code Online (Sandbox Code Playgroud)

这最终会抛出这个错误:

ObjectDereferencedError:无法为属性'Queue.users'发出更改事件 - 类型的父对象已被垃圾回收.

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

我不知道这意味着什么.我想我在这里缺乏一些关于sqlalchemy的基本知识(我是一个sqlalchemy noob).这是怎么回事?

zzz*_*eek 9

lecture.queues.first().users.append(user)
Run Code Online (Sandbox Code Playgroud)

它的意思是:

第一个()方法命中数据库并生成一个对象,我没有关注你的映射,但我猜它是一个Queue对象.

然后,您访问Queue上的"users"集合.

此时,Python本身垃圾收集队列 - 一旦"用户"被返回,它就不会被引用到任何地方.这是引用计数垃圾收集的工作原理.

然后,您尝试将"用户"附加到"用户".SQLAlchemy必须跟踪对所有映射属性的更改,如果你说Queue.name = "some name",SQLAlchemy需要在父Queue对象中注册它,以便它知道要刷新它.如果你说Queue.users.append(someuser)同样的想法,它需要向父母注册变更事件.

SQLAlchemy无法做到这一点,因为Queue它已经消失了.因此提出了这个消息.SQLAlchemy 在这里对父项有一个弱参数,因此它确切地知道发生了什么(我们无法阻止它,因为当我们在对象模型中创建不必要的引用循环时,人们会非常沮丧).

解决方案非常简单,也更容易阅读,即将查询结果分配给变量:

queue = lecture.queues.first()
queue.users.append(user)
Run Code Online (Sandbox Code Playgroud)