Search code examples
databasedjangodatabase-designdjango-modelsdjango-treebeard

Django: How do I model a tree of heterogeneous data types?


I need to store a tree data structure in my database, for which I plan on using django-treebeard or possibly django-mptt. My source of confusion is that each node could be one of three different possible types: root nodes will always be a type A entity, leaf nodes a type C entity, and anything in between will be a type B entity. I would like to know the best way to model this situation.

update: I first tried model inheritance, and I think that this could be the best way to go. Unfortunately django-treebeard's public API isn't really designed to handle this. I ended up getting it to work with GenericForeignKey. Thank you very much for the answers.


Solution

  • How about using a generic relation from the model which will hold the tree structure to the content object for the node it represents?

    from django.db import models
    from django.contrib.contenttypes.models import ContentType
    from django.contrib.contenttypes import generic
    
    class Node(models.Model):
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        object = generic.GenericForeignKey('content_type', 'object_id')
    

    This could potentially result in a lot of queries when retrieving content objects for the full tree, but there are ways and means of reducing the number of queries required.

    # Assuming mptt, as I'm not familiar with treebeard's API
    
    # 1 query to retrieve the tree
    tree = list(Node.tree.all())
    
    # 4 queries to retrieve and cache all ContentType, A, B and C instances, respectively
    populate_content_object_caches(tree)