I'm using Django to write a blog app, and I'm trying to implement a hierarchical category structure. Each category has a "parent" ForeignKey pointing back to the same Category model. I want to allow admins to add categories, and I want the interface to allow them to select a category's parent category. However, I want to avoid I'm-my-own-grandpa situations, so I want to limit the available choices of categories to those which do not have category in question as an ancestor.
Right now, I'm controlling this from the view:
parent_candidates = list(Category.objects.all())
pruned_parent_list = [cat for cat in parent_candidates if instance.id not in cat.getHierarchy()]
where instance is the category being edited and getHierarchy() is a method to get a list of ancestor ids.
There are a number of problems with this approach. In particular, it uses an extra database hit to get the list of all categories and it makes me write the selection mechanism into my template by looping through pruned_parent_list to get the options, when I'd really rather just specify a widget.
Is there any better way to do this? I know I can add custom validation on the back-end to prevent this, but why give users the option?