Git Product home page Git Product logo

django-activeurl's Introduction

django-activeurl

Easy-to-use active URL highlighting for Django

Features

  • automatic highlighting of currently active <a> tags via CSS class
  • automatic highlighting of parent <a> tags for menus
  • removes boring / hardcoded stuff from your life!
  • href="#" never causes highlighting for compatibility with techniques such as bootstrap nav.

Usage

After loading the template library via

{% load activeurl %}

the following code snippet will be rendered like this if request.full_path() starts with /some_page/:

{% activeurl %}
    <ul>
        <li> <!-- this <li> will render as <li class="active"> -->
            <a href="/some_page/">
                some_page
            </a>
        </li>
        <li>
            <a href="/another_page/">
                another_page
            </a>
        </li>
    </ul>
{% endactiveurl %}

Note: The content of {% activeurl %}…{% endactiveurl %} must have valid root tag (i.e. <ul> or <div>, etc) -- otherwise an exception will be raised.

Installation

Python 2.7+, 3.4+ are supported.

  1. Install the stable version using pip:

    pip install django-activeurl
    

    or install the in-development version using pip:

    pip install -e git+git://github.com/hellysmile/django-activeurl#egg=django_activeurl
    
  2. In your settings.py add the following:

    INSTALLED_APPS = (
        ...
        'django_activeurl',
        ...
    )
    
    TEMPLATE_CONTEXT_PROCESSORS = (
        ...
        'django.core.context_processors.request',
        ...
    )
  3. The lxml library is required and thus additional libraries need to be installed to build it:

    • Ubuntu:

      sudo apt-get install libxml2 libxml2-dev libxslt-dev build-essential python-dev
      sudo ldconfig
      
    • Fedora:

      sudo yum groupinstall 'Development Tools'
      sudo yum install libxslt-devel libxml2 libxml2-devel python-devel
      sudo ldconfig
      
    • MacOS X:

      brew install libxml2 libxslt
      sudo update_dyld_shared_cache -force
      
    • Windows: A pre-built lxml binary can be found here

    • Clouds: There's a 99.99% chance that lxml will build out of the box.

Options

menu ="yes|no" (default: "yes")

Should hierarchical menus be supported? There are two different ways to declare an active status:

  • the starts-with logic toggles the active state if request.get_full_path() starts with the contents of the <a href= attribute.
  • the equals logic toggles the active state if request.get_full_path() is identical to the contents of the <a href= attribute.

You might want to use starts-with logic in hierarchical menus/submenus to not only highlight the current position but also every parent position. So, with request.get_full_path() being /menu/submenu the following snippet will render accordingly:

{% activeurl menu="yes" parent_tag="div" %}
    <div>
        <div>  <!-- This will render as <div class="active"> -->
            <a href="/menu/">
                menu
            </a>
            <div>  <!-- This will also render as <div class="active"> -->
                <a href="/menu/submenu/">
                    submenu
                </a>
            </div>
        </div>
    </div>
{% endactiveurl %}

The equals logic works best for non-hierarchical menus where only those items should be highlighted whose href-attribute perfectly match request.get_full_path():

{% activeurl menu="no" parent_tag="div" %}
    <div>
        <div>
            <a href="/menu/">
                menu
            </a>
        </div>
        <div>
            <a href="/menu/submenu/">
                submenu
            </a>
        </div>
    </div>
{% endactiveurl %}

ignore_params ="yes|no" (default: "no")

ignore_params will ignore GET parameters of URLs, e.g. /accounts/login/ will match /accounts/login/?next=/accounts/signup/.

parent_tag ="div|li|self|…" (default: "li")

parent_tag defines that a parent element -- and not the <a> tag itself -- should be declared active when there's a match in URLs. When you need to change the CSS class of the <a> tag, just enter "self".

css_class ="<string>" (default: "active")

Defines what CSS class to add to an active element.

Configuration

The default options can be set in settings.py as well:

ACTIVE_URL_KWARGS = {
    'css_class': 'active',
    'parent_tag': 'li',
    'menu': 'yes',
    'ignore_params': 'no'
}
ACTIVE_URL_CACHE = True
ACTIVE_URL_CACHE_TIMEOUT = 60 * 60 * 24  # 1 day
ACTIVE_URL_CACHE_PREFIX = 'django_activeurl'

By default django-activeurl will try to retrieve a previously rendered HTML node from Django's caching backend before active URLs are looked for and a new HTML tree is built. You can disable the cache with ACTIVE_URL_CACHE = False.

In addition, ACTIVE_URL_CACHE_TIMEOUT can be used to define a timeout for keys to expire. The default value is one day.

The last configuration option is ACTIVE_URL_CACHE_PREFIX (which is django_activeurl by default) and defines which name to use in Django's caching backend.

Tests

pip install tox
tox

Jinja2

Vanilla Jinja2 configuration:

from jinja2 import Environment

from django_activeurl.ext.django_jinja import ActiveUrl


env = Environment(
    extensions=[ActiveUrl]
)

Options can be omitted:

{% activeurl css_class="active", menu="yes", parent_tag="li", ignore_params="no" %}
    <ul>
        <li>
            <a href="/page/">page</a>
        </li>
        <li>
            <a href="/other_page/">other_page</a>
        </li>
    </ul>
{% endactiveurl %}

If you're using django-jinja you need to load the ActiveUrl in settings.py.

Django 1.8+ Jinja2 environment loader example can be found in tests.

Background

For building the HTML element tree django-activeurl uses lxml, which is one of the best HTML parsing tools around. More info and benchmarks can be found at habrahabr.ru (in russian). Note that there's no content rebuilding inside the template tag when no active URLs are found, so there's no impact on performance.

django-activeurl's People

Contributors

bitdeli-chef avatar bmispelon avatar crystalstiletto avatar hellysmile avatar jnns avatar jonashaag avatar jor123 avatar meloncafe avatar rosslote avatar tony avatar voidus avatar wbphp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-activeurl's Issues

Remove classy-tags?

@hellysmile

Open to removing classy-tags?

It is including six as a dependency now, and we could potential get the equivalent safely without needing an extra package.

Confusing behaviour with href='#'

Using 0.1.9, <a href='#'...> did not cause the parent to be highlighted, as only fragments with text were ignored[1]. This changed starting with 0.1.10[2], which breaks our usage.

I believe using <a href='#' to expand submenus on small screens is common enough to deserve special consideration, as it is the approach recommended by bootstrap.[3]

I'd suggest special-casing href='#'. Alternatively, I think that the docs should probably mention this and suggest a workaround.

What do you think?

[1]

href = re.sub(r'\#.+', '', href)

[2]
href = href._replace(fragment='')

[3] https://getbootstrap.com/docs/4.0/components/navs/#tabs-with-dropdowns

Django 4.0.1 Support

Hello,

I am trying to add this library to my latest Django project (Django 4.0.1) on Python 3.10

I have followed the instructions but it seems some things in Django 4.0 have changed, and I am wondering if there is a way to continue making this library work with Django 4.

Here is the current status:

'TEMPLATES' variable seems to have changed a bit, I tried this:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.core.context_processors.request',
            ],
        },
    },
]

However, PyCharm is highlighting django.core.context_processors.request', so I imagine this needs to be corrected

The final error I am getting from python manage.py runserver is django.template.library.InvalidTemplateLibrary: Invalid template library specified. ImportError raised when trying to load 'django_activeurl.templatetags.activeurl': cannot import name 'urlquote' from 'django.utils.http' (/Users/me/.local/share/virtualenvs/my-project-KF_-XuuK/lib/python3.10/site-packages/django/utils/http.py)

Any ideas?

Thank you so much in advance for this wonderful library, and if there is any way I can contribute on adding an update to make django-activeurl work with Django 4, let me know.

Dalton

Base url configuration

Is there a way to configure it for when my nav items' url doesn't start at root, but with a fixed base pattern like like '/foo/section1' and '/foo/section2'?

Does this work with generated URLs?

Hello! Just looking at this project, I noticed that the README only shows examples of hard-coded URLs (/menu/), which seems to me unusual: I am used to projects with routes defined in urlconf, and all links are generated with reverse / url. Does activeurl work if the templates use url? what if there is href="{{ some_variable}}"?

If the answer is yes, then I suggest making it clear in the doc!
Thanks for considering this

Move to jazzband?

@hellysmile Are you open to moving this to jazzband, or prefer keeping it here?

Rationale: Keeping up to date with new django versions

Roadmap

  1. i18n_patterns skip "/"

  2. option to skip GET variables - 41b25cc

  3. option to swap "base" href, rather then request.get_full_path() use custom callback function

  4. add support for <a href="">, <a href="/"> - f74e392

KeyError at /

I've installed this according to the manual and all I get when I access any page is the "KeyError". I'm using Django 1.9.6 and Python 2.7.11

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.