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.leafs
and Node.subleafs
definitions to the file leaf.py
where class Leaf (node)
has been defined and appended with the former definitions like below:
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)
Node.leafs = db.relationship (Leaf, cascade='all', lazy='dynamic',
primaryjoin=Node.id==Leaf.root_id)
Node.subleafs = db.relationship (Leaf, cascade='all', lazy='dynamic',
primaryjoin=Node.id==Leaf.base_id)
A disadvantage of this is that people have to from models import Leaf
if they want to access Node.leafs
and Node.subleafs
, but since they had to do this anyway (even if Node.leafs
and Node.subleafs
had been defined as backrefs within class 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.