sqlalchemy:对象引用

2024-09-30 18:28:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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

创作讲座

^{pr2}$

从某个控制器调用的所有控制器

newlec = createLecture(user, courseobj)

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

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

redirect(somewhere)

最后会抛出以下错误:

ObjectDereferencedError:无法为属性“”发出更改事件队列.用户'-类型的父对象已被垃圾回收。在

createPad中的lecture.queues.first().users.append(user)。在

我不知道这意味着什么。我想我缺乏一些关于sql炼金术的基本知识(我是个sqlalchemy noob)。发生什么事?在


Tags: 用户newdbmakesession讲座notescommit
2条回答
lecture.queues.first().users.append(user)

意思是:

第一个()方法命中数据库并生成一个对象,我没有跟踪您的映射,但我猜测它是一个队列对象。在

然后,访问队列上的“users”集合。在

此时,Python本身垃圾收集队列-一旦返回“users”,就不会在任何地方引用它。这就是reference counting垃圾回收的工作原理。在

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

SQLAlchemy不能这样做,因为Queue不见了。因此,消息被提出。SQLAlchemy在这里有一个weakref,因此它可以确切地知道发生了什么(我们不能阻止它,因为当我们在对象模型中创建不必要的reference cycles时,人们会非常不安)。在

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

^{pr2}$

我做了一系列重构,并在实例化过程中放入了与某些对象相对应的对象,这使得事情变得整洁了许多。不知怎么的,问题消失了。在

我做了一件不同的事,那就是在我的多对多的关系中,我把backref改为a后台数据库():

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'))

相关问题 更多 >