我的课程Node
和Leaf (Node)
如下所示:
class Node (db.Model):
__mapper_args__ = {'polymorphic_identity':'node', 'polymorphic_on':'type'}
id = db.Column (db.Integer, primary_key=True)
type = db.Column ('type', db.String (16))
root_id = db.Column (db.Integer, db.ForeignKey (id))
nodes = db.relationship ('Node',
cascade='all', lazy='dynamic',
primaryjoin='Node.root_id==Node.id',
backref=db.backref('root', remote_side=id))
leafs = db.relationship ('Leaf',
cascade='all', lazy='dynamic',
primaryjoin='Leaf.root_id==Node.id')
def __init__ (self, root):
self.root = root
和
class Leaf (Node):
__mapper_args__ = {'polymorphic_identity': 'leaf'}
leaf_id = db.Column (db.Integer, db.ForeignKey ('node.id'), primary_key=True)
def __init__ (self, root):
super (Leaf, self).__init__ (root)
具有以下属性(摘自我的测试):
def test_polymorphic (self):
base_node, leaf_of_base, node_of_base, leaf_of_node = self.create ()
self.commit ([base_node, leaf_of_base, node_of_base, leaf_of_node])
leaf, node = base_node.nodes.all ()
self.assertEqual (type (leaf), Leaf)
self.assertTrue (isinstance (leaf, Node))
self.assertTrue (isinstance (leaf, Leaf))
self.assertEqual (type (node), Node)
self.assertTrue (isinstance (node, Node))
self.assertFalse (isinstance (node, Leaf))
所以Node.nodes
包含叶子对象(这就是我想要的),而Node.leafs
会导致仅叶子对象(这也很好)
现在,我想介绍一下我喜欢的Node.nodes_except_leafs
:
class Node (db.Model):
...
nodes_except_leafs = property (lambda self: self.nodes.filter_by (type='node'))
这实际上有效,但我不认为这是最好的解决方案,因为使用这种方法,我会错过一个例如以下类型:
class NodeEx (Node):
__mapper_args__ = {'polymorphic_identity': 'nodeex'}
nodex_id = db.Column (db.Integer, db.ForeignKey ('node.id'), primary_key=True)
def __init__ (self, root):
super (NodeEx, self).__init__ (root)
由于Node.nodes.filter_by (type='node')
会错过NodeEx
的所有NodeEx.type == 'nodeex'
个对象。
什么是Node.nodes_except_leafs
更好的解决方案,它返回所有非叶子或派生叶子对象(可能来自Node
的子类)? THX。
答案 0 :(得分:3)
下面怎么样:
class Node (db.Model):
...
# original
nodes_except_leafs = property (lambda self: self.nodes.filter(Node.type != 'leaf'))
# use outer join (to class) to filter out the Leaf(++)
nodes_except_leafs = property (lambda self: self.nodes.outerjoin(Leaf, Node.id == Leaf.leaf_id).filter(Leaf.id == None))