I have the classes Node and Leaf (Node) as shown below: It works fine, but I’d prefer to shift the leafs and subleafs definitions to the Leaf (Node) class. How do I achieve that?
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')
base_id = db.Column (db.Integer, db.ForeignKey (id))
subnodes = db.relationship ('Node',
cascade='all', lazy='dynamic',
primaryjoin='Node.base_id==Node.id',
backref=db.backref('base', remote_side=id))
subleafs = db.relationship ('Leaf',
cascade='all', lazy='dynamic',
primaryjoin='Leaf.base_id==Node.id')
def __init__ (self, root):
self.base = root.base if root and root.base else root
self.root = root
and
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)
I tried this, but failed (partially):
class Leaf (Node):
__mapper_args__ = {'polymorphic_identity': 'leaf'}
leaf_id = db.Column (db.Integer, db.ForeignKey ('node.id'), primary_key=True)
_x = db.relationship ('Node', backref=db.backref ('leafs',
cascade='all', lazy='dynamic', primaryjoin='Leaf.root_id==Node.id'))
_y = db.relationship ('Node', backref=db.backref ('subleafs',
cascade='all', lazy='dynamic', primaryjoin='Leaf.base_id==Node.id'))
def __init__ (self, root):
super (Leaf, self).__init__ (root)
My delete test cases did not like this (just deleting the base/root node in the tree and relying on cascade='all'), and complained with:
CircularDependencyError: Circular dependency detected. Cycles: set([DeleteState(<Leaf at 0x22789d0>)]) all edges: set([(DeleteState(<Leaf at 0x22789d0>), DeleteState(<Leaf at 0x22789d0>))])
The reason I want to shift the definitions is, because I do not want to extend Node with definitions for every sub-class of Leaf (Node), which I might introduce later. Further, I definitely don’t need _x and _y, since I already have Leaf.root and Leaf.base (provided by Node); but omitting them (_x = & _y =) called for trouble like:
AttributeError: 'Node' object has no attribute 'leafs'
I guess I’m required to use something in Leaf (Node) to attach the relations to, even though I was not required to use any backrefs in my original definitions for leafs and subleafs in Node. Thx.
Well, after some trying I’ve found a solution, that is not perfect, but does the job: I just moved the
Node.leafsandNode.subleafsdefinitions to the fileleaf.pywhereclass Leaf (node)has been defined and appended with the former definitions like below:A disadvantage of this is that people have to
from models import Leafif they want to accessNode.leafsandNode.subleafs, but since they had to do this anyway (even ifNode.leafsandNode.subleafshad been defined as backrefs withinclass Leaf (Node)), it is allright.If somebody finds a solution, where the relationships are defined as backrefs within
class Leaf (Node), I’d be glad to hear from; thx.