假设我在同一个数据库表上有两个不同的类型(单表继承):
class Employee(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String, nullable = False)
discriminator = db.Column('type', String)
__mapper_args__ = {'polymorphic_on': discriminator}
class Manager(Employee):
__mapper_args__ = {'polymorphic_identity': 'manager'}
division = db.Column(db.String, nullable = False)
role = db.Column(db.String, nullable = False)
class Worker(Employee):
__mapper_args__ = {'polymorphic_identity': 'worker'}
title = db.Column(db.String, nullable = False)
(是的,我使用的是Flask SqlAlchemy,而不是普通的香草)现在我该如何将一个声明性模型转换为另一个。也就是说,如果一个“工人”被提升为“经理”呢我该怎么做?我是否必须编写原始SQL来实现这一点?在
抱歉,如果这之前有人问过,但我找不到谷歌。请注意,这是一个人为的例子。在
它是kludgy,它会导致一个警告,但是您可以通过设置属性强行修改discriminator列:
这会引起一个警告,比如
^{pr2}$你可以忽略这一点,只要你能解决它会引起的问题。最安全的方法是在提交后立即关闭会话(
session.close()
)或从中删除所有内容(session.expunge_all()
)。在如果必须,您可以通过从会话中删除John(
session.expunge(john_smith)
)来解决John对象的问题。您必须小心;对john_smith
的任何剩余引用都将保留该对象,不过谢天谢地,他将与session
分离,并且您不允许对它们做任何操作。在我也尝试了其他明显的选择。两者都不起作用,但都说明了SQLAlchemy的
Session
对象存储的内容以及如何:session.refresh(john_smith)
失败,返回这是因为SQLAlchemy在数据库中查询一个
Worker
(不是Employee
),并且找不到一个名为John Smith的名字,因为数据库现在知道John是因为他的type
列中的新值而得到提升的。session.expire(john_smith)
成功,但未能将John更新为一个新类,随后对他的任何访问都将导致SQLAlchemy仍然认为John是一个
Worker
,它试图以Worker
的身份查询他。这是因为他仍然坚持session.identity_map
,看起来是这样的:所以有一个John,明确地列为
Worker
对象。当您从会话中expunge()
John时,字典中的这个条目将被清除。当您expire()
他时,他所有映射的属性都被标记为过时,但他仍然存在于字典中。我建议修改你的对象模型。当一个对象和另一个对象的属性一样工作时,对象模型将从重新思考中受益。在这种情况下,
Worker.title
也可以是“经理”。在还有,部门经理作为它自己的对象划分,效果更好。尤其是因为一个部门可能会和工人有一对多的关系。在
类似于一个
Division
对象,其中一个管理器的ForeignKey
指向一个Employee
对象。Employee
对象将具有title属性;在Employee.__init__()
中,您可以手动检查该员工是否是任何部门的经理,然后将Employee.title
从__init__()
设置为“manager”。在相关问题 更多 >
编程相关推荐