Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top