1

j'ai les classes Node et Leaf (Node) comme indiqué ci-dessous:sqlalchemy et le filtrage des requêtes polymorphiques

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 

et

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) 

avec les propriétés suivantes (extrait de mes tests):

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)) 

Donc Node.nodesdans cludes objets feuille (ce qui est ce que je veux), et Node.leafs résultats en seulement objets feuilles (c'est aussi bien).

Maintenant, je voudrais vous présenter Node.nodes_except_leafs, que j'ai aimé:

class Node (db.Model): 
    ... 
    nodes_except_leafs = property (lambda self: self.nodes.filter_by (type='node')) 

Cela fonctionne en fait, mais je ne pense pas que ce soit la meilleure solution possible, puisque l'utilisation de cette approche, je d manquer un noeud de par exemple type:

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) 

Depuis Node.nodes.filter_by (type='node') raterait tous NodeEx objets avec NodeEx.type == 'nodeex'.

Quelle serait une meilleure solution pour Node.nodes_except_leafs qui renvoie tous les objets non-feuille-ou-dérivations-de-feuille (dérivé éventuellement d'une sous-classe de Node)? THX.

Répondre

3

Que diriez-vous ci-dessous:

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)) 
+0

Thx pour la réponse: Il fonctionne en principe, mais est en fait pas ce que je suis à la recherche, puisque votre suggestion n'omettre leafs qui ont été instancié à l'aide d'un sous -classe de 'Leaf' par exemple 'leafex = FeuilleEx (..)' où 'classe LeafEx (Feuille)' avec 'LeafEx.type == 'leafex''. (testé) – hsk81

+0

mis à jour la réponse avec une version qui résout les préoccupations exprimées – van

+0

Thx, cela a résolu mon problème; P – hsk81

Questions connexes