django-sitetree

repository·master·Indexed 43 days ago

https://github.com/idlesign/django-sitetree

A reusable Django application for managing site structure, menus, and breadcrumbs through hierarchical trees. It allows for the definition of site trees via the Django admin or dynamically in code, supporting template tags in titles, named URLs in URIs, and access control via the standard Django permissions system. Key features include internationalization support via register_i18n_trees() and specialized template tags like {% sitetree_menu %}, {% sitetree_breadcrumbs %}, and {% sitetree_tree %].

Tokens
18.8K
Snippets
70
Records
87
Agent score
54%

What's inside django-sitetree

  1. Overview of django-sitetree

    master

    django-sitetree is a reusable Django application designed to manage site structure, menus, and breadcrumb navigation. It allows you to define a hierarchical site tree via the Django admin interface or dynamically through code.

    Key features include:

    • Hierarchical Site Trees: Define pages using URIs or named URLs associated with human-friendly titles.
    • Dynamic Content: Support for Django template tags in titles (e.g., {{ user.first_name }}) and Django named URLs in URIs (e.g., users-personal).
    • Access Control: Restrict access to specific tree items using the standard Django permissions system.
    • Flexible Navigation: Generate menus, breadcrumbs, and full site trees for your templates.
  2. Understand the core concepts of django-sitetree

    master

    django-sitetree is a Django application that manages site structure, menus, breadcrumbs, and full site trees. It works by defining 'site trees' where each item represents a page or a set of pages via a URI (or named URL) and a human-friendly title.

    Key features include:

    • Dynamic Content: Supports Django template tags in titles (e.g., {{ user.first_name }}) and Django named URLs in URIs (e.g., users-personal).
    • Access Control: Integration with Django's permission system allows you to restrict access to specific sitetree items to authenticated users or specific permission groups.
    • Hybrid Tree Definition: You can define trees via the Django Admin interface or dynamically in your Python code, and combine both types.
  3. How dynamic trees work

    master

    Dynamic trees allow you to compose and register sitetrees at runtime (e.g., in config.ready() or urls.py) rather than relying solely on database-stored trees. This is useful for structuring app-defined trees into existing hierarchies dynamically.

    To use dynamic trees, you must:

    1. Use compose_dynamic_tree() to create a tree structure or gather trees from an app.
    2. Register them using register_dynamic_trees().
    3. (Optional) Set SITETREE_DYNAMIC_ONLY = True in your settings to prevent the application from querying the database for trees/items, which is efficient if you only use dynamic trees.

    When calling register_dynamic_trees(), you can use the reset_cache=True argument to ensure newly registered trees are rendered immediately by dropping and recreating the cache.

    from sitetree.toolbox import tree, item, register_dynamic_trees, compose_dynamic_tree 
    
    register_dynamic_trees(
        # Gather all trees from the 'books' app
        compose_dynamic_tree('books'),
    
        # Gather trees from 'books' and attach them to the 'main' tree root
        compose_dynamic_tree('books', target_tree_alias='main'),
    
        # Gather trees from 'books' and attach them to a specific item in 'main' tree
        compose_dynamic_tree('books', target_tree_alias='main', parent_tree_item_alias='for_books'),
    
        # Define a tree structure directly during registration
        compose_dynamic_tree((
            tree('dynamic', items=(
                item('dynamic_1', 'dynamic_1_url', children=(
                    item('dynamic_1_sub_1', 'dynamic_1_sub_1_url'),
                )),
                item('dynamic_2', 'dynamic_2_url'),
            )),
        )),
    
        reset_cache=True
    )
  4. Configure dynamic URLs in Site Tree items

    master

    To associate a sitetree item with a dynamic Django URL pattern, use the following format in the URL field of the item:

    [named_url_pattern] [argument1] [argument2] ...

    Requirements:

    • You must check the URL as Pattern checkbox in the item's Additional settings.
    • The arguments passed must match the names defined in your urls.py pattern.
    • Arguments can be template variables (e.g., category.name) that will be resolved when the tree is rendered.

    Example Scenario: If your urls.py contains:

    url(r'^(?P<category_name>\S+)/(?P<entry_name>\S+)/$', 'detailed_entry', name='entry-detailed'),

    To map a tree item to this URL, set the item's URL field to: entry-detailed category.name entry.name

    # urls.py example
    url(r'^(?P<category_name>\S+)/(?P<entry_name>\S+)/$', 'detailed_entry', name='entry-detailed'),
    url(r'^(?P<category_name>\S+)/$', 'detailed_category', name='category-detailed'),
  5. How internationalized sitetrees work

    master

    Internationalization in django-sitetree relies on a naming convention for tree aliases.

    • Generic Alias: The primary name used in templates (e.g., my_tree). This acts as the fallback if no specific locale tree is available.
    • Internationalized Alias: Trees named with a locale suffix (e.g., my_tree_en, my_tree_ru).

    When register_i18n_trees() is called, the library maps the generic alias to these locale-specific versions. The resolution depends on the current active locale determined by Django's translation system (django.utils.translation.activate).

  6. Define dynamic site tree items using template tags and named URLs

    master

    To make your site tree scalable and dynamic, you can use Django named URLs in the URI field and Django template tags in the Title field. This allows the tree to adapt to different users or data contexts without manual entry for every single page.

    Example configuration in the Django admin:

    • URI: Use the named URL pattern (e.g., users-personal).
    • Title: Use template tags to inject dynamic data (e.g., User Called {{ user.first_name }}).
      URI                           Title
        /                           - Site Root
        |_users/                    - Site Users
          |_users-personal user.id  - User Called {{ user.first_name }}
  7. Integrate django-modeltranslation for localized tree items

    master

    If you prefer using django-modeltranslation over the built-in SiteTree Internationalization machinery, you can localize tree items by following these steps:

    1. Create a custom tree item model by inheriting from TreeItemBase.
    2. Configure SiteTree to use your custom model via the SITETREE_MODEL_TREE_ITEM setting.
    3. Customize the Admin interface by creating an admin class that inherits from both TreeItemAdmin and TranslationAdmin, then applying it using override_item_admin.
    4. Register the model with modeltranslation by defining TranslationOptions for the fields you wish to translate (e.g., title, hint, description).
    # 1. myapp/models.py
    from sitetree.models import TreeItemBase
    
    class MyTranslatableTreeItem(TreeItemBase):
        """This model will be used by modeltranslation."""
    
    # 2. settings.py
    SITETREE_MODEL_TREE_ITEM = 'myapp.MyTranslatableTreeItem'
    
    # 3. admin.py
    from modeltranslation.admin import TranslationAdmin
    from sitetree.admin import TreeItemAdmin, override_item_admin
    
    class CustomTreeItemAdmin(TreeItemAdmin, TranslationAdmin):
        """This allows admin contrib to support translations for tree items."""
    
    override_item_admin(CustomTreeItemAdmin)
    
    # 4. myapp/translation.py
    from modeltranslation.translator import translator, TranslationOptions
    from .models import MyTranslatableTreeItem
    
    class TreeItemTranslationOptions(TranslationOptions):
        fields = ('title', 'hint', 'description')
    
    translator.register(MyTranslatableTreeItem, TreeItemTranslationOptions)
  8. Customize the tree handler using SITETREE_CLS

    master

    If you need to perform custom logic on tree items (such as special ordering or title manipulation) that is not supported by default, you can provide a custom tree handler by subclassing sitetreeapp.SiteTree.

    To implement a custom handler:

    1. Create a new class that inherits from sitetreeapp.SiteTree.
    2. Override relevant methods, such as .apply_hook(), to manipulate tree items before they are rendered.
    3. Register your class in your Django settings.py using the SITETREE_CLS setting, providing the full dotted path to your subclass.
    # myapp/mysitetree.py
    from sitetree.sitetreeapp import SiteTree
    
    class MySiteTree(SiteTree):
        def apply_hook(self, tree_items, sender):
            # Custom logic here
            return tree_items
    
    # myproject/settings.py
    SITETREE_CLS = 'myapp.mysitetree.MySiteTree'
  9. Define a sitetree within a Django app

    master

    To define a sitetree for a specific application, create a sitetrees.py file within that app's directory. You must define a module-level attribute named sitetrees containing one or more tree definitions. Use the tree and item functions from sitetree.toolbox to build the structure.

    Key functions:

    • tree(alias, items=[...]): Defines a tree with a specific alias and its child items.
    • item(title, url, children=[...], in_menu=True, in_sitetree=True, access_by_perms=None): Defines a tree item.

    Note: If you have extended the Tree or TreeItem models with custom fields, you can pass those field values as keyword arguments to the item function.

    from sitetree.toolbox import tree, item
    
    sitetrees = (
      tree('books', items=[
          item('Books', 'books-listing', children=[
              item('Book named "{{ book.title }}"', 'books-details', in_menu=False, in_sitetree=False),
              item('Add a book', 'books-add', access_by_perms=['booksapp.allow_add']),
              item('Edit "{{ book.title }}"', 'books-edit', in_menu=False, in_sitetree=False)
          ])
      ]),
    )
  10. Create a tree using Django Admin

    master

    You can build a site tree structure through the Django Admin interface:

    1. Create a Site Tree: In the admin panel, add a new Site Tree and provide an alias (e.g., maintree). This alias is used to reference the tree in template tags.
    2. Add Items: Add Site Tree Items to build the hierarchy.
    3. Configure URLs as Patterns: When creating items that represent dynamic URLs (using Django named URL patterns), you must check the URL as Pattern checkbox in the Additional settings section of the item.
    4. Use Template Variables: You can use Django template variable syntax (e.g., {{ category.id }}) in the Title field of a tree item. These will be resolved at runtime just like in a standard Django template.
  11. Optimize sitetree performance for large trees

    master

    When working with large sitetrees, you can reduce performance overhead by following these structural and configuration best practices:

    1. Simplify Tree Structure

    Reduce the total number of sitetree items by unifying redundant nodes. Instead of creating unique category nodes for every specific type, use generic category nodes with dynamic templates (e.g., using {{ category.title }}) to group items under a single branch.

    2. Avoid 'URL as Pattern' Items

    Do not use the URL as Pattern sitetree item option. For better performance, use hardcoded URLs instead.

    3. Minimize Access Restrictions

    Avoid applying access permission restrictions (access rights) to sitetree items unless they are strictly required for your use case.

    4. Implement Caching

    • Use Django's template caching machinery.
    • Use a fast Django cache backend.