https://github.com/smileychris/django-navtag
Keep that navigation logic in the presentation layer where it belongs.
https://github.com/smileychris/django-navtag
Last synced: 2 months ago
JSON representation
Keep that navigation logic in the presentation layer where it belongs.
- Host: GitHub
- URL: https://github.com/smileychris/django-navtag
- Owner: SmileyChris
- License: mit
- Created: 2013-07-17T22:25:45.000Z (almost 13 years ago)
- Default Branch: master
- Last Pushed: 2021-04-11T22:32:09.000Z (about 5 years ago)
- Last Synced: 2025-04-12T21:07:15.884Z (about 1 year ago)
- Language: Python
- Homepage: https://pypi.python.org/pypi/django-navtag
- Size: 40 KB
- Stars: 33
- Watchers: 5
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- License: LICENSE
Awesome Lists containing this project
README
``{% nav %}`` tag
=================
.. image:: https://badge.fury.io/py/django-navtag.svg
:target: https://badge.fury.io/py/django-navtag
.. image:: https://codecov.io/gh/SmileyChris/django-navtag/branch/master/graph/badge.svg
:target: https://codecov.io/gh/SmileyChris/django-navtag
A simple Django template tag to handle navigation item selection.
.. contents::
:local:
:backlinks: none
Installation
------------
Install the package using pip:
.. code:: bash
pip install django-navtag
Usage
-----
Add the app to your ``INSTALLED_APPS`` setting:
.. code:: python
INSTALLED_APPS = (
# ...
'django_navtag',
)
Give your base template a navigation block something like this:
.. code:: jinja
{% load navtag %}
{% block nav %}
{% nav text ' class="selected"' %}
{% endblock %}
In your templates, extend the base and set the navigation location:
.. code:: jinja
{% extends "base.html" %}
{% block nav %}
{% nav "home" %}
{{ block.super }}
{% endblock %}
.. note::
This works for multiple levels of template inheritance, due to the fact
that only the first ``{% nav %}`` call found will change the ``nav``
context variable.
Hierarchical navigation
-----------------------
To create a sub-menu you can check against, simply dot-separate the item:
.. code:: jinja
{% nav "about_menu.info" %}
This will be pass for both ``{% if nav.about_menu %}`` and
``{% if nav.about_menu.info %}``.
Using a different context variable
----------------------------------
By default, this tag creates a ``nav`` context variable. To use an alternate
context variable name, call ``{% nav [item] for [var_name] %}``:
.. code:: jinja
{% block nav %}
{% nav "home" for sidenav %}
{{ block.super }}
{% endblock %}
Setting the text output by the nav variable
-------------------------------------------
As shown in the initial example, you can set the text return value of the
``nav`` context variable. Use the format ``{% nav text [content] %}``. For
example:
.. code:: jinja
{% nav text "active" %}
- Home
- Contact
Alternately, you can use boolean comparison of the context variable rather than
text value:
.. code:: jinja
If using a different context variable name, use the format
``{% nav text [content] for [var_name] %}``.
Comparison operations
---------------------
The ``nav`` object supports comparison operations for more flexible navigation handling:
**Exact matching with** ``==``:
.. code:: jinja
{% nav "products.phones" %}
{% if nav == "products.phones" %}
{# True - exact match #}
{% endif %}
{% if nav == "products" %}
{# False - not exact #}
{% endif %}
**Special patterns with** ``!``:
.. code:: jinja
{% nav "products.electronics" %}
{% if nav == "products!" %}
{# True - matches any child of products #}
{% endif %}
{% if nav == "products!clearance" %}
{# True - matches children except 'clearance' #}
{% endif %}
**Component checking with** ``in``:
.. code:: jinja
{% nav "products.electronics.phones" %}
{% if "products" in nav %}
{# True - component exists #}
{% endif %}
{% if "electronics" in nav %}
{# True - component exists #}
{% endif %}
{% if "tablets" in nav %}
{# False - component doesn't exist #}
{% endif %}
These operations also work with sub-navigation:
.. code:: jinja
{% nav "products.electronics.phones" %}
{% if nav.products == "electronics.phones" %}
{# True #}
{% endif %}
{% if "electronics" in nav.products %}
{# True #}
{% endif %}
Iteration
---------
The ``nav`` object supports iteration over its active path components:
.. code:: jinja
{% nav "products.electronics.phones" %}
{% for component in nav %}
{{ component }}
{# Outputs: products, electronics, phones #}
{% endfor %}
This also works with sub-navigation:
.. code:: jinja
{% nav "products.electronics.phones" %}
{% for component in nav.products %}
{{ component }}
{# Outputs: electronics, phones #}
{% endfor %}
The ``{% navlink %}`` tag
-------------------------
The ``{% navlink %}`` tag provides a convenient way to create navigation links that automatically change based on the active navigation state. It works as a block tag that renders different HTML elements depending on whether the navigation item is active.
Basic usage:
.. code:: jinja
{% load navtag %}
{% nav text 'active' %}
{% nav "products" %}
The tag will render:
- ``...`` - when the nav item is active
- ``...`` - when the nav item is a parent of the active item
- ``...`` - when the nav item is not active
The second parameter uses Django's built-in ``{% url %}`` tag syntax, so you can pass URL names with arguments:
.. code:: jinja
{% navlink 'product' 'product_detail' product_id=product.id %}
{{ product.name }}
{% endnavlink %}
Custom attributes
~~~~~~~~~~~~~~~~~
You can customize the attribute added to active links using ``{% nav text %}`` with an attribute format:
.. code:: jinja
{% nav text ' aria-selected="true"' %}
{% nav "home" %}
{% navlink 'home' 'home_url' %}Home{% endnavlink %}
{# Renders: Home #}
Special matching patterns
~~~~~~~~~~~~~~~~~~~~~~~~~
The ``{% navlink %}`` tag supports special patterns for more precise matching:
**Children-only pattern** (``item!``):
.. code:: jinja
{% nav "courses.special" %}
{% navlink 'courses' 'course_list' %}All Courses{% endnavlink %}
{# Renders as link with class="active" #}
{% navlink 'courses!' 'course_detail' %}Course Details{% endnavlink %}
{# Renders as link with class="active" - only when nav is a child of courses #}
When ``courses`` is active (not a child), the first link is active but the second becomes a ````.
**Exclusion pattern** (``item!exclude``):
.. code:: jinja
{% nav "courses.special" %}
{% navlink 'courses!list' 'course_detail' %}Course (not list){% endnavlink %}
{# Renders as link - active for any child except 'list' #}
{% navlink 'courses!special' 'course_detail' %}Course (not special){% endnavlink %}
{# Renders as span - 'special' is excluded #}
You can also use these patterns with ``{% if %}`` statements:
.. code:: jinja
{% if nav == "courses!" %}
{# True - matches any child of courses #}
{% endif %}
Alternate nav context
~~~~~~~~~~~~~~~~~~~~~
To use a different navigation context variable, prefix the nav item with the variable name:
.. code:: jinja
{% nav "products" for mainnav %}
{% nav "settings" for sidenav %}
{% navlink 'mainnav:products' 'product_list' %}Products{% endnavlink %}
{% navlink 'sidenav:settings' 'user_settings' %}Settings{% endnavlink %}