How to Use Hierarchical Registries¶
Define parent-child relationships between registries so that child choices depend on a parent selection.
Defining Hierarchical Registries¶
from django_stratagem import Registry, HierarchicalRegistry, Interface, HierarchicalInterface
class CategoryRegistry(Registry):
implementations_module = "categories"
class SubcategoryRegistry(HierarchicalRegistry):
implementations_module = "subcategories"
parent_registry = CategoryRegistry
class Electronics(Interface):
registry = CategoryRegistry
slug = "electronics"
class Phones(HierarchicalInterface):
registry = SubcategoryRegistry
slug = "phones"
parent_slug = "electronics" # Only valid under electronics
HierarchicalInterface¶
Extends Interface with parent validation:
parent_slugSingle parent slug this implementation is valid for.
parent_slugsList of parent slugs this implementation is valid for.
If neither is set, the implementation is valid for all parents.
class MultiParentChild(HierarchicalInterface):
registry = SubcategoryRegistry
slug = "accessories"
parent_slugs = ["electronics", "clothing"] # Valid under multiple parents
@classmethod
def is_valid_for_parent(cls, parent_slug: str) -> bool:
# Automatically checks parent_slug / parent_slugs
...
Key Methods¶
# Get the parent registry
SubcategoryRegistry.get_parent_registry() # CategoryRegistry
# Get children valid for a specific parent
children = SubcategoryRegistry.get_children_for_parent("electronics")
# {"phones": <class Phones>, ...}
# Get choices filtered by parent
choices = SubcategoryRegistry.get_choices_for_parent("electronics")
# [("phones", "Phones"), ...]
# Validate a parent-child relationship
SubcategoryRegistry.validate_parent_child_relationship("electronics", "phones") # True
# Get the full hierarchy map
hierarchy = SubcategoryRegistry.get_hierarchy_map()
# {"electronics": ["phones", "tablets"], "clothing": ["shirts"]}
RegistryRelationship¶
Manages the global parent-child relationship graph:
from django_stratagem import RegistryRelationship
# Get child registries for a parent
children = RegistryRelationship.get_children_registries(CategoryRegistry)
# Get all descendants recursively
descendants = RegistryRelationship.get_all_descendants(CategoryRegistry)
# Clear all relationships (useful in tests)
RegistryRelationship.clear_relationships()
Using in Models¶
Hierarchical registries work with HierarchicalRegistryField to enforce parent-child validation at the model level:
from django_stratagem import HierarchicalRegistryField
class MyModel(models.Model):
category = CategoryRegistry.choices_field()
subcategory = HierarchicalRegistryField(
registry=SubcategoryRegistry,
parent_field="category",
)
See How to Use Model Fields for details.
Using in Forms¶
Use HierarchicalRegistryFormField and HierarchicalFormMixin to build forms with dependent dropdowns:
from django_stratagem import HierarchicalRegistryFormField, HierarchicalFormMixin
class MyForm(HierarchicalFormMixin, forms.ModelForm):
class Meta:
model = MyModel
fields = ["category", "subcategory"]
See How to Use Forms, Widgets, and the Admin for details.
Using in the Admin¶
HierarchicalRegistryAdmin handles hierarchical fields automatically with JavaScript-driven dynamic updates:
from django_stratagem.admin import HierarchicalRegistryAdmin
@admin.register(MyModel)
class MyModelAdmin(HierarchicalRegistryAdmin):
pass
See How to Use Forms, Widgets, and the Admin for details.