Compare request.path with a reversed url in Django template

我的未来我决定 提交于 2019-12-05 09:13:36

You can use a custom template tag

from django import template

register = template.Library()

@register.simple_tag
def active(request, pattern):
    path = request.path
    if path == pattern:
        return 'active'
    return ''

Then usage is sort of like this in your template:

{% load my_tags %}

{% url orders_list as orders %}
<li class="{% active request orders %}"> 
    <a href="{{ orders }}"> Orders </a> 
</li>

You can modify the template tag as you wish.

Building on Josh's answer, you can use a simple 'if' tag:

{% url 'orders_list' as orders_list_url %}
<a{% if request.path == orders_list_url %} class="active"{% endif %}
  href="{{ orders_list_url }}">Orders</a>
MaestroFJP

A better version of the top answer would be to reverse the viewname:

{% url_active 'reverse_viewname' %}

This version doesn't require you to pass in the request. Instead, we indicate that the tag needs the context and then get the request from that.

from django import template
from django.core.urlresolvers import reverse

register = template.Library()

@register.simple_tag(takes_context=True)
def url_active(context, viewname):
    request = context['request']
    current_path = request.path
    compare_path = reverse(viewname)
    if current_path == compare_path:
        return 'active'
    else:
        return ''

Inspired by cougar's answer:

$("ul.nav [href='"+window.location.pathname+"']").parents("li").addClass('active');

This solution is plain JS, and works for Bootstrap's navigation bar. For the OP's scenario one can use:

$("[href='"+window.location.pathname+"']").addClass('active-tab');

A solution with an if-then-else option:

from django import template
from django.template.base import Node, NodeList, TemplateSyntaxError

register = template.Library()

class IfCurrentViewNode(Node):
    child_nodelists = ('nodelist_true', 'nodelist_false')

    def __init__(self, view_name, nodelist_true, nodelist_false):
        self.view_name = view_name
        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false

    def __repr__(self):
        return "<IfCurrentViewNode>"

    def render(self, context):
        view_name = self.view_name.resolve(context, True)
        request = context['request']
        if request.resolver_match.url_name == view_name:
            return self.nodelist_true.render(context)
        return self.nodelist_false.render(context)


def do_ifcurrentview(parser, token):
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument"
                                  " (path to a view)" % bits[0])
    view_name = parser.compile_filter(bits[1])
    nodelist_true = parser.parse(('else', 'endifcurrentview'))
    token = parser.next_token()
    if token.contents == 'else':
        nodelist_false = parser.parse(('endifcurrentview',))
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()
    return IfCurrentViewNode(view_name, nodelist_true, nodelist_false)

@register.tag
def ifcurrentview(parser, token):
    """
    Outputs the contents of the block if the current view match the argument.

    Examples::

        {% ifcurrentview 'path.to.some_view' %}
            ...
        {% endifcurrentview %}

        {% ifcurrentview 'path.to.some_view' %}
            ...
        {% else %}
            ...
        {% endifcurrentview %}
    """
    return do_ifcurrentview(parser, token)

You could calculate whatever you need (request.path = reverse('orders_list') for example) in your view and pass the result to the template. In the view (python code) you can manipulate the path as much as you like.

You can check if one URL is the prefix of the other.

cougar

Try this jQuery statement:

$("[href='{{ request.path }}']").parents("li").addClass('active');

Usage: {% url_active "home" "other-view" "and-so-on" success="active-specific-class" %}

from django import template

register = template.Library()


@register.simple_tag(takes_context=True)
def url_active(context, *args, **kwargs):
    if 'request' not in context:
        return ''

    request = context['request']
    if request.resolver_match.url_name in args:
        return kwargs['success'] if 'success' in kwargs else 'active'
    else:
        return ''

I figured out a hacked way to do it in jQuery... but I'm still open for a better solution.

jQuery:

var tab_list = {
    'orders-tab' : '{% url orders_list %}',
    'users-tab'  : '{% url users_list %}',
    'vendors-tab': '{% url vendors_list %}',
    'places-tab' : '{% url places_list %}'
}

$(document).ready(function() {
    for(var property in tab_list) {
        if('{{ request.path }}' == tab_list[property]) {
            $('#' + property).addClass('active-tab')
            break
        }
    }
})

HTML:

<ul id="tabs" class="fl">
    <li><a href="#" id="dashboard-tab" class="dashboard-tab">Dashboard</a></li>
    <li><a href="{% url orders_list %}" id="orders-tab">Orders</a></li>
    <li><a href="{% url users_list %}" id="users-tab">Users</a></li>
    <li><a href="{% url vendors_list %}" id="vendors-tab">Vendors</a></li>
    <li><a href="{% url places_list %}" id="places-tab">Places</a></li>
</ul>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!