我有一个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
从某个控制器调用的所有控制器
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)。发生什么事?在
意思是:
第一个()方法命中数据库并生成一个对象,我没有跟踪您的映射,但我猜测它是一个队列对象。在
然后,访问队列上的“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后台数据库():
相关问题 更多 >
编程相关推荐