Compare request.path with a reversed url in Django template

五迷三道 提交于 2019-12-07 04:50:18

问题


I understand that request.path will give me the current URL.

I am currently working on my base.html template with CSS tabs and I want the template to know which tab is currently "active" and pass class="active-tab" to an <a> tag.

So I wanted to do something like

<a href="{% url orders_list %}"
    {% if request.path = reverse('orders_list') %}
        class="active-tab"
    {$ endif %}
>Orders</a>

But I'm sure you can't do that if comparison. I also only want the base (?) URL ignoring any GET parameters.

Any suggestions or tips also welcomed. Thanks in advance!


回答1:


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.




回答2:


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>



回答3:


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 ''



回答4:


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');



回答5:


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)



回答6:


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.




回答7:


Try this jQuery statement:

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



回答8:


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 ''



回答9:


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>


来源:https://stackoverflow.com/questions/10263482/compare-request-path-with-a-reversed-url-in-django-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!