{"id":18457249,"url":"https://github.com/redsolution/django-catalog-tree","last_synced_at":"2025-07-11T07:08:45.074Z","repository":{"id":51092749,"uuid":"63678355","full_name":"redsolution/django-catalog-tree","owner":"redsolution","description":null,"archived":false,"fork":false,"pushed_at":"2023-10-19T07:28:50.000Z","size":302,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-08T05:33:41.462Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redsolution.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-19T09:01:10.000Z","updated_at":"2023-10-19T07:28:54.000Z","dependencies_parsed_at":"2025-04-08T05:43:28.718Z","dependency_job_id":null,"html_url":"https://github.com/redsolution/django-catalog-tree","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/redsolution/django-catalog-tree","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redsolution%2Fdjango-catalog-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redsolution%2Fdjango-catalog-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redsolution%2Fdjango-catalog-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redsolution%2Fdjango-catalog-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redsolution","download_url":"https://codeload.github.com/redsolution/django-catalog-tree/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redsolution%2Fdjango-catalog-tree/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264753341,"owners_count":23658858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T08:13:50.703Z","updated_at":"2025-07-11T07:08:45.019Z","avatar_url":"https://github.com/redsolution.png","language":"JavaScript","readme":"# Django catalog tree\n\nOpen source catalog management system based on the Django framework and django-mptt library.\n\n## Requirements\n- Django 1.11\n- Python 2.7\n- django-classy-tags \u003e=0.3 and \u003c=0.9.0\n- django-mptt 0.9.*\n\n## Installation and basic usage\n\n1. Install package\n\n    ``pip install git+git://github.com/oldroute/django-catalog-tree``\n\n2. Create application for your custom catalog models, for example ``custom_catalog``\n\n    **models.py**\n\n    ```python\n    from django.db import models\n    from catalog.models import CatalogBase\n    ...\n\n\n\n    class Root(CatalogBase):\n        title = models.CharField(max_length=400)\n\n        def get_absolute_url(self):\n            return reverse('catalog-root')\n\n        def __str__(self, *args, **kwargs):\n            return self.title\n\n\n    class Section(CatalogBase):\n        title = models.CharField(max_length=400)\n\n        def __str__(self):\n            return self.title\n\n\n    class Product(CatalogBase):\n        leaf = True # cannot have children\n        title = models.CharField(max_length=400)\n\n        def __str__(self):\n            return self.title\n\n\n    class Category(CatalogBase):\n        leaf = True # cannot have children\n        title = models.CharField(max_length=400)\n        items = models.ManyToManyField(Item, blank=True, null=True, related_name='categories')\n\n        def __str__(self):\n            return self.title\n\n    ```\n\n    This is example of simple catalog structure based on four typical models:\n\n    - ``Root`` - represent catalog root page\n    - ``Section`` - model for grouping products based on inheritance\n    - ``Product`` - endpoint of catalog tree - represent product page\n    - ``Category``- special model for grouping products from any section by common attribute\n\n    **admin.py**\n\n    ```python\n    from django.contrib import admin\n    from catalog.admin import CatalogItemBaseAdmin\n    from .models import Root, Section, Product, Category\n    ...\n\n\n    @admin.register(Root)\n    class RootAdmin(CatalogItemBaseAdmin):\n        model = Root\n\n        def has_add_permission(self, request):\n            return not bool(Root.objects.exists())\n\n        def has_delete_permission(self, request, obj=None):\n            return False\n\n\n    @admin.register(Product)\n    class ProductAdmin(CatalogItemBaseAdmin):\n        model = Product\n\n\n    @admin.register(Section)\n    class SectionAdmin(CatalogItemBaseAdmin):\n        model = Section\n\n\n    @admin.register(Category)\n    class CategoryAdmin(CatalogItemBaseAdmin):\n        model = Category\n    ```\n    Create other app files like ``apps.py``. Application setup details are not relevant to this guide.\n\n3. Configure your setting file:\n\n    ``CATALOG_MODELS`` - list of models that will be available for creation in the admin catalog interface. Simple example of configuration:\n\n    ```python\n    INSTALLED_APPS += ['catalog', '\u003cPROJECT_ROOT\u003e.custom_catalog']\n\n    CATALOG_MODELS = [\n        'custom_catalog.Section',\n        'custom_catalog.Product',\n        'custom_catalog.Category',\n    ]\n    ```\n\n5. Add urlpattern to main urls.py:\n\n    ```python\n    urlpatterns = [\n        ...\n        url(r'^catalog/', include('catalog.urls')),\n        ...\n    ]\n    ```\n\n5. Create templates\n\n    For each catalog model your need to create template. Follow next templates structure:\n\n    - catalog/\n        - breadcrumbs.html (default template exist)\n        - children_tag.html (default template exist)\n        - product.html\n        - root.html\n        - section.html\n        - category.html\n\n     The object instance is accessible in the template through the variable ``object`` or by model name. Consider how to work with data in a templates:\n\n    **catalog/base.html**\n    ```html\n    {% load catalog_tags %}\n    ...\n    \u003ch1\u003e{{ object.title }}\u003c/h1\u003e\n\n    \u003cdiv class='breadcrumbs'\u003e\n        {% block breadcrumbs %}\n            {{ block.super }}\n            {% catalog_breadcrumbs object %}\n        {% endblock %}\n    \u003c/div\u003e\n\n    {% block content %}{% endblock %}\n    ```\n    In this examle  ``{% catalog_breadcrumbs object %}`` include rendered catalog bredcrumbs for object (for customize see template ``breadcrumbs.html``). For example: *Catalog-\u003e Section-\u003e Product*\n\n    **catalog/section.html**\n\n    ```html\n    {% extends 'catalog/base.html' %}\n    {% load catalog_tags %}\n\n    {% block content %}\n        \u003cdiv class='products'\u003e\n            \u003c!-- Show products here --\u003e\n        \u003c/div\u003e\n    {% endblock %}\n    ```\n   In this example we need display  products of current section. Consider ways to display a list of products\n\n   ``{% catalog_children for object %}`` - render ``children_tag.html`` with section all children.\n\n   ``{% catalog_children for object type product %}`` - render ``children_tag.html`` with section **products-children**.\n\n   ``{% catalog_children for object type product descendants all %}`` - render ``children_tag.html`` with section **products-descendants**.\n\n   ``{% catalog_children for object type product descendants all as descendants %}`` - get section **product-descendants** as varible ``descendants``\n\n6. Apply migrations and run local server\n\n    ```python\n    python manage.py migrate\n    python manage.py runserver\n    ```\n\n7. Create catalog root and some catalog items in admin catalog app.\n\n**Configure is done!**\n\n## Advansed usage\n#### About requests by catalog tree\n\nAll catalog items consist of two records:\n- **content_object** - is instance of your custom models (like Product, Section) with represent custom fields.\n- **tree** - node to represent postion in catalog structure.\n\nExample №1. Get section tree node: ``section.tree.get()``\n\nExample №2. Get section children tree nodes ``section.tree.get().get_children()`` - QuerySet in result\n\nExample №3. Get section children products\n\n```python\nfrom catalog.utils import get_content_objects\nproducts = get_content_objects(section.tree.get().get_children()) # list in result\n```\nExample №4. Get section children products sorted by catalog tree structure\n\n```python\nfrom catalog.utils import get_content_objects, get_sorted_content_objects\nsorted_products = get_sorted_content_objects(get_content_objects(section.tree.get().get_children()))\n```\nSee other tree methods in [django-mptt docs](https://django-mptt.github.io/django-mptt/models.html)\n\n#### Available catalog events:\nIf your need to control catalog states you may handle following signals\n- **content_object_moved** - fired for content_object when tree node moved. Signal provides next kwargs:\n    - instance - content_object\n    - parent_from - old parent content_object (moved from)\n    - parent_to - new parent content_object (moved to)\n- **content_object_parent_changed** - fired for content_object when tree node moved by tree and\nwhen old and new parent do not match. Provides the same kwargs.\n- **content_object_created** - fired for content_object when a new record is created. Provides next kwargs:\n    - instance - content_object\n    - parent - parent content_object (None for root nodes)\n- **node_moved** - fired for tree node when it moved by tree. Provide next kwargs:\n    - instance - tree node\n    - target - new parent tree node (moved to)\n    - position - one of predefined values, see django-mptt [docs](https://django-mptt.github.io/django-mptt/mptt.forms.html?highlight=position#mptt.forms.TreeNodePositionField)\n\nUse case example:\n\n**signals.py**\n```python\nfrom mptt.signals import node_moved\nfrom catalog.models import TreeItem\nfrom catalog.signals import content_object_parent_changed, content_object_created\nfrom \u003cPROJECT_ROOT\u003e.custom_catalog.models import Product\n\ndef handler(sender, instance, **kwargs):\n    # for every signal **kwargs contain their provides kwargs\n    # for example parent_from = kwargs.get(\"parent_from\")\n    # Do something\n\nnode_moved.connect(handler, sender=TreeItem)\ncontent_object_created(handler)\ncontent_object_parent_changed.connect(handler)\ncontent_object_moved(handler)\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredsolution%2Fdjango-catalog-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredsolution%2Fdjango-catalog-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredsolution%2Fdjango-catalog-tree/lists"}