I have a tagging system, where the tags exist in a hierarchy. I've used django-mptt
to build the Tag model. I want to display a group of tags differently if every sibling in the group is a leaf node.
To do this, I want a model method called all_siblings_leaf()
. Here's my first take on that method:
def all_siblings_leaf(self):
"""Return True if all siblings, including self, are leaf nodes."""
siblings = self.get_siblings()
return all([sibling.is_leaf_node() for sibling in siblings])
This works, but it's one trip to the db for the get_siblings()
call. When I want to call all_siblings_leaf()
, I've already queried for all the tags I want to use. Using this method repeatedly with a set of several hundred tags means several hundred new db calls.
Since I already have all the tags, I feel like I should be able to get the information about leaf nodes without any additional trips to the db. Here's what I've come up with:
def all_siblings_leaf(self, all_tags):
"""Return True if all siblings including self are leaf nodes.
all_tags should be a queryset that used select_related('parent')
"""
if self.level == 0:
siblings = [t for t in all_tags if t.level == 0]
else:
siblings = [t for t in all_tags if t.parent == self.parent]
return all([sibling.is_leaf_node() for sibling in siblings])
This works; on a page where this method is used many times, there's only one trip to the db as measured by debug toolbar.
This feels really kludgy, going through each other node and checking if it has the same parent, since we've already fetched every tag's parent information. Is this a reasonable approach, or is there a simpler solution? I'm calling the method from a template while looping through tags, if that makes a difference.