I have to store a tree data structure during my database, that I intend on using django-treebeard or even django-mptt. My supply of confusion is the fact that each node might be among three different possible types: root nodes will be a kind A entity, leaf nodes a kind C entity, and anything among is a type B entity. I must know the easiest method to model this case.
update: When i first attempted model inheritance, and i believe that this may be the easiest method to go. Regrettably django-treebeard's public API is not really designed additional. I wound up setting it up to utilize GenericForeignKey. Thanks greatly for that solutions.
Your three types are most likely simplest handled as FK associations using the fundamental tree.
The tree could be homogenous -- class
MyNode is really a direct subclass of
treebeard.Node. Your node may have a flag (Root, Middle, Leaf) and FK's for any or B or C. This enables you some SQL-like versatility in querying MyNode instance.
This enables your tree to develop. A node can begin like a type C (leaf) after which morph to some type B (intermediate). You alter the status, and alter the FK's.
The choice is a little more complicated.
class MyA( treebeard.Node ): pass class MyB( treebeard.Node ): pass class MyC( treebeard.Node ): pass
Within this situation, you cannot "morph" a node. Whenever a node begins like a
MyC, and will get children, you need to take away the original
MyC instance, and change it having a
MyB version which has a new node growing up. This is not impossible, but it may be painful.
What about utilizing a generic relation in the model that will contain the tree structure towards the content object for that node it signifies?
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 might potentially result in many queries when locating content objects for that full tree, but you will find ways and means of reducing the amount of queries needed.
# 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)
Well, a great deal has already been accomplished for you, in ways, because roots, leaves yet others happen to be naturally recognized through the tree API. You are able to call is_root() and it is_leaf() on individual nodes to differentiate them.
Leaves as well as in-betweens could possibly be the same kind of entity and contain the same kind of data, considering that the information is construed and utilized by the applying based on tests areleaf().
Roots are somewhat special... they may want to hold information pertinent towards the whole tree, and you will just like a simple way to find information about particular roots and hold extra data. You may do that having a model which has a one-to-one relationship having a root node (possibly using the save method overloaded and checking to verify the node it indicates is_root() before permitting the save).
My point overall is you might not want to get very fancy to complete what you would like. The excellence you are making has already been exemplified in the idea of the tree and it is API and also you could most likely implement different behavior with similar fundamental data by checking the context from the node.
If your tree structure is an essential part of the application, think about using another thing than the usual relational database. Maybe neo4j?