resursive function not incrementing as expected - python/django
Question: I'm creating a tree app using Django models. Basically a user inputs the names
of different nodes, and if a node is connected to another, a recursive
function adds 1 to the parent node's "nodes" property. As soon as I add nodes
that increase a parents' total to >2, it stops incrementing and stays at two.
Here's the code:

    
    
    class Node(models.Model):
        name = models.CharField(max_length=200)
        parent = models.ForeignKey('self', null=True)
        nodes = models.IntegerField(default=0)
    
        def __unicode__(self):
            return self.name
    

The user inputs text. For example, let's say a user enters the following:

    
    
    "animal(dog)"
    "dog(golden retriever)"  # animal nodes should be 2 (and it is)
    "golden retriever(old yeller)" # animal nodes should now be 3 but it remains 2
    

This should generate a tree of this structure:

    
    
         animal   (3 nodes)
       /         
    dog      (2 nodes)      
      |
    golden retriever   (1 node)
      | 
     old yeller  (0 nodes)
    

Somehow the node_ancestors method functions correctly only at first. Any ideas
on what's going wrong in my views?

    
    
    def node_ancestors(node):  
    
        ancestor = node.parent 
    
        if ancestor != None: 
    
            ancestor.nodes += 1
            print ancestor, " just added a node.   it now has %d nodes. " % (ancestor.nodes)
            node.save()
            node_ancestors(ancestor)
    
    def index(request):
        nodes = Node.objects.all()
        node_names = [a.name for a in nodes]
    
    if request.method == 'POST':  
        node_string = request.POST.get('get_node')
        print node_string
        index = node_string.find('(')
        parent = node_string[0:index]
        child = node_string[index+1:len(node_string)-1]
    
        if parent not in moment_names and child not in node_names:
            parent = Node(name=parent, nodes=1)
            parent.save()
            child = Node(name=child, parent=parent)
            child.save()
            print "parent is", parent
            print "child is", child
            print "parent nodes: ", parent.nodes
            print "child nodes: ", child.nodes
    
        elif parent in node_names and child not in node_names:
            parent_model = nodes.get(name=parent)
    
            node_ancestors(parent_model)  # adds 1 to all nodes superior to parent node
    
            child = Node(name=child, parent=parent_model)
    
            child.save()
    
    
        elif parent not in node_names and child in node_names:
            parent = Node(name=parent, nodes=child_model.nodes+1)
            parent.save()
            print "parent is", parent
    
    return render(request, 'nodes_app/index.html')
    


Answer: For these kind of things, you could maybe use Django MPTT (<http://django-
mptt.github.io/django-mptt/>), it is designed to build tree models and has a
[lot of built-in methods](http://django-mptt.github.io/django-
mptt/models.html) to get/display ancestors/children.

Here is a simple example built from the code you gave :

    
    
    from django.db import models
    from mptt.models import MPTTModel, TreeForeignKey
    
    
    class Species(MPTTModel):
        name = models.CharField(max_length=50, unique=True)
        parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
    
        class MPTTMeta:
            order_insertion_by = ['name']
    
    dog = Species()
    dog.name = "Dog"
    dog.save()
    
    golden = Species()
    golden.name = "Golden Retriever"
    golden.parent = dog
    golden.save()
    
    old = Species()
    old.name = "Old Yeller"
    old.parent = golden
    old.save()
    
    
    print(dog.level)    # 0
    print(golden.level) # 1
    print(old.level)    # 2
    
    ancestors = old.get_ancestors(include_self=True)
    
    for each species in ancestors:
        print(species.name)
    
    # Dog
    # Golden Retriever
    # Old Yeller
    

