Package: django-polymorphic-tree
django-polymorphic-treeThis package combinesdjango-mpttwithdjango-polymorphic.
You can write Django models that form a tree structure where each node can be a different model type.Example uses:Build a tree of organisation and company types (e.g.Partner,Reseller,GroupandCustomer)Build a tree of a root node, category nodes, leaf nodes, each with custom fields.Build a todo list of projects, categories and items.Build a book of chapters, sections, and pages.OriginThis code was created indjango-fluent-pages, and extracted to become a separate package.
This was done during contract work atLeukeleu(known fordjango-fiber).InstallationFirst install the module, preferably in a virtual environment:pip install django-polymorphic-treeOr install the current repository:pip install -e git+https://github.com/django-polymorphic/django-polymorphic-tree.git#egg=django-polymorphic-treeThe main dependencies aredjango-mpttanddjango-polymorphic,
which will be automatically installed.ConfigurationNext, create a project which uses the application:cd ..
django-admin.py startproject demoAdd the following tosettings.py:INSTALLED_APPS+=('polymorphic_tree','polymorphic','mptt',)UsageThe main feature of this module is creating a tree of custom node types.
It boils down to creating a application with 2 files:Themodels.pyfile should define the custom node type, and any fields it has:fromdjango.dbimportmodelsfromdjango.utils.translationimportgettext_lazyas_frompolymorphic_tree.modelsimportPolymorphicMPTTModel,PolymorphicTreeForeignKey# A base model for the tree:classBaseTreeNode(PolymorphicMPTTModel):parent=PolymorphicTreeForeignKey('self',blank=True,null=True,related_name='children',verbose_name=_('parent'))title=models.CharField(_("Title"),max_length=200)classMeta(PolymorphicMPTTModel.Meta):verbose_name=_("Tree node")verbose_name_plural=_("Tree nodes")# Create 3 derived models for the tree nodes:classCategoryNode(BaseTreeNode):opening_title=models.CharField(_("Opening title"),max_length=200)opening_image=models.ImageField(_("Opening image"),upload_to='images')classMeta:verbose_name=_("Category node")verbose_name_plural=_("Category nodes")classTextNode(BaseTreeNode):extra_text=models.TextField()# Extra settings:can_have_children=FalseclassMeta:verbose_name=_("Text node")verbose_name_plural=_("Text nodes")classImageNode(BaseTreeNode):image=models.ImageField(_("Image"),upload_to='images')classMeta:verbose_name=_("Image node")verbose_name_plural=_("Image nodes")Theadmin.pyfile should define the admin, both for the child nodes and parent:fromdjango.contribimportadminfromdjango.utils.translationimportgettext_lazyas_frompolymorphic_tree.adminimportPolymorphicMPTTParentModelAdmin,PolymorphicMPTTChildModelAdminfrom.importmodels# The common admin functionality for all derived models:classBaseChildAdmin(PolymorphicMPTTChildModelAdmin):GENERAL_FIELDSET=(None,{'fields':('parent','title'),})base_model=models.BaseTreeNodebase_fieldsets=(GENERAL_FIELDSET,)# Optionally some custom admin codeclassTextNodeAdmin(BaseChildAdmin):pass# Create the parent admin that combines it all:classTreeNodeParentAdmin(PolymorphicMPTTParentModelAdmin):base_model=models.BaseTreeNodechild_models=(models.CategoryNode,models.TextNode,# custom admin allows custom edit/delete view.models.ImageNode,)list_display=('title','actions_column',)classMedia:css={'all':('admin/treenode/admin.css',)}admin.site.register(models.CategoryNode,BaseChildAdmin)admin.site.register(models.TextNode,TextNodeAdmin)admin.site.register(models.ImageNode,BaseChildAdmin)admin.site.register(models.BaseTreeNode,TreeNodeParentAdmin)Thechild_modelsattribute defines which admin interface is loaded for theeditanddeletepage.
The list view is still rendered by the parent admin.TestsTo run the included test suite, execute:./runtests.pyTo test support for multiple Python and Django versions, you need to follow steps below:install project requirements in virtual environmentinstall python 2.7, 3.4, 3.5, 3.6 python versions through pyenv (See pyenv (Linux) or Homebrew (Mac OS X).)create .python-version file and add full list of installed versions with which project have to be tested, example:2.6.9
2.7.13
3.4.5
3.5.2
3.6.0run tox from the repository root:pip install tox
toxPython 2.7, 3.4, 3.5 and 3.6 and django 1.8, 1.10 and 1.11 are the currently supported versions.TodoSphinx DocumentationContributingThis module is designed to be generic. In case there is anything you didn’t like about it,
or think it’s not flexible enough, please let us know. We’d love to improve it!If you have any other valuable contribution, suggestion or idea,
please let us know as well because we will look into it.
Pull requests are welcome too. :-)