1

I want to create a generic decision tree using SQL Alchemy. That is, each node has zero or more children of any type, and the task is to evaluate some expression using the tree root, which will pass on the logic to the children using extending classes.

I have defined the following base class:

from flask_sqlalchemy import Model, SQLAlchemy, DefaultMeta
from abc import ABCMeta, abstractmethod
from sqlalchemy import Column, Integer, String, Date, Boolean, ForeignKey, Text, Float, Unicode

db = SQLAlchemy(model_class=BaseModel)

class BaseModel(Model):
    pass

class ModelABCMeta(DefaultMeta, ABCMeta):
    pass

class RuleBaseNode(db.Model, metaclass=ModelABCMeta):
    """Generic base class representing a node in a decision tree"""

    id = Column(Integer, primary_key=True)
    type = Column(String(50))

    parent_node_type = Column(Unicode(255), nullable=True)
    parent_node_id = Column(Integer, nullable=True)

    parent_node = generic_relationship(parent_node_type, parent_node_id)

    __mapper_args__ = {
        'polymorphic_on': type,
        'polymorphic_identity': 'node'
    }

    @abstractmethod
    def eval(self, input) -> bool:
        """Evaluates an input to a boolean"""
        pass

Now the question is how to add an attribute of the node children.

Usually, I would use relationship with backref, but I couldn't find anything in the documentation.

I would want such a property:

class RuleBaseNode(db.Model, metaclass=ModelABCMeta):
    ...
    @property
    def sub_nodes():
        return ...

Now I guess I could implement some sort of the following, but I would guess it won't work with querying an abstract class

def get_sub_nodes(session, node):
    session.query(RuleBaseNode).filter(RuleBaseNode.parent_node == node).all()
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
Mugen
  • 8,301
  • 10
  • 62
  • 140

0 Answers0