Je viens de faire ma première petite application Web à Django et j'adore ça. Je suis sur le point de commencer à convertir un ancien site de production PHP en Django et, dans le cadre de son modèle, une barre de navigation.
En PHP, je compare l'URL de chaque option de navigation à l'URL actuelle dans le code du modèle et applique une classe CSS si elles s'alignent. C'est horriblement malpropre.
Y a-t-il quelque chose de mieux pour Django ou un bon moyen de gérer le code dans le modèle?
Pour commencer, comment pourrais-je obtenir l’URL actuelle?
J'utilise l'héritage de modèles pour personnaliser la navigation. Par exemple:
base.html
<html>
<head>...</head>
<body>
...
{% block nav %}
<ul id="nav">
<li>{% block nav-home %}<a href="{% url home %}">Home</a>{% endblock %}</li>
<li>{% block nav-about %}<a href="{% url about %}">About</a>{% endblock %}</li>
<li>{% block nav-contact %}<a href="{% url contact %}">Contact</a>{% endblock %}</li>
</ul>
{% endblock %}
...
</body>
</html>
about.html
{% extends "base.html" %}
{% block nav-about %}<strong class="nav-active">About</strong>{% endblock %}
Vous n'avez pas besoin d'un if pour le faire, regardez le code suivant:
tags.py
@register.simple_tag
def active(request, pattern):
import re
if re.search(pattern, request.path):
return 'active'
return ''
urls.py
urlpatterns += patterns('',
(r'/$', view_home_method, 'home_url_name'),
(r'/services/$', view_services_method, 'services_url_name'),
(r'/contact/$', view_contact_method, 'contact_url_name'),
)
base.html
{% load tags %}
{% url 'home_url_name' as home %}
{% url 'services_url_name' as services %}
{% url 'contact_url_name' as contact %}
<div id="navigation">
<a class="{% active request home %}" href="{{ home }}">Home</a>
<a class="{% active request services %}" href="{{ services }}">Services</a>
<a class="{% active request contact %}" href="{{ contact }}">Contact</a>
</div>
ça y est . pour les détails de la mise en œuvre, regardez:
gnuvince.wordpress.com
110j.wordpress.com
J'ai bien aimé la propreté de 110j ci-dessus, alors j'ai pris l'essentiel et refactorisé pour résoudre les 3 problèmes que j'avais avec:
C'est ici:
tags.py:
from Django import template
register = template.Library()
@register.tag
def active(parser, token):
args = token.split_contents()
template_tag = args[0]
if len(args) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
return NavSelectedNode(args[1:])
class NavSelectedNode(template.Node):
def __init__(self, patterns):
self.patterns = patterns
def render(self, context):
path = context['request'].path
for p in self.patterns:
pValue = template.Variable(p).resolve(context)
if path == pValue:
return "active" # change this if needed for other bootstrap version (compatible with 3.2)
return ""
urls.py:
urlpatterns += patterns('',
url(r'/$', view_home_method, {}, name='home_url_name'),
url(r'/services/$', view_services_method, {}, name='services_url_name'),
url(r'/contact/$', view_contact_method, {}, name='contact_url_name'),
url(r'/contact/$', view_contact2_method, {}, name='contact2_url_name'),
)
base.html:
{% load tags %}
{% url home_url_name as home %}
{% url services_url_name as services %}
{% url contact_url_name as contact %}
{% url contact2_url_name as contact2 %}
<div id="navigation">
<a class="{% active request home %}" href="home">Home</a>
<a class="{% active request services %}" href="services">Services</a>
<a class="{% active request contact contact2 %}" href="contact">Contact</a>
</div>
Je suis l'auteur de Django-lineage que j'ai écrit spécifiquement pour résoudre cette question: D
Je me suis énervé en utilisant la méthode jpwatts (parfaitement acceptable) dans mes propres projets et je me suis inspiré de la réponse de 110j. La lignée ressemble à ceci:
{% load lineage %}
<div id="navigation">
<a class="{% ancestor '/home/' %}" href="/home/">Home</a>
<a class="{% ancestor '/services/' %}" href="/services/">Services</a>
<a class="{% ancestor '/contact/' %}" href="/contact/">Contact</a>
</div>
ancestor
est simplement remplacé par "actif" si l'argument correspond au début de l'URL de la page en cours.
Les arguments variables et la résolution inverse de type {% url %}
complet sont également pris en charge. J'ai semé quelques options de configuration, je l'ai étoffé et emballé pour que tout le monde puisse l'utiliser.
Si quelqu'un est intéressé, lisez un peu plus à ce sujet sur:
Depuis Django 1.5 :
Dans toutes les vues génériques basées sur les classes (ou dans toute vue héritée de ___ contextMixin basée sur des classes), le dictionnaire de contexte contient une variable de vue. qui pointe vers l'instance View.
Ainsi, si vous utilisez de telles vues, vous pouvez ajouter quelque chose de semblable à breadcrumbs
en tant que champ de niveau de classe et l’utiliser dans vos modèles.
Exemple de code de vue:
class YourDetailView(DetailView):
breadcrumbs = ['detail']
(...)
Dans votre modèle, vous pouvez l'utiliser de cette manière:
<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>
Si vous souhaitez également "surligner" les éléments de navigation parent, vous devez étendre la liste breadcrumbs
:
class YourDetailView(DetailView):
breadcrumbs = ['dashboard', 'list', 'detail']
(...)
... et dans votre modèle:
<a href="/dashboard/" {% if 'dashboard' in view.breadcrumbs %}class="active"{% endif %}>Dashboard</a>
<a href="/list/" {% if 'list' in view.breadcrumbs %}class="active"{% endif %}>List</a>
<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>
C'est une solution simple et propre qui fonctionne plutôt bien avec la navigation imbriquée.
Vous pouvez appliquer une classe ou un identifiant à l'élément body de la page, plutôt qu'à un élément de navigation spécifique.
HTML:
<body class="{{ nav_class }}">
CSS:
body.home #nav_home,
body.about #nav_about { */ Current nav styles */ }
Je le fais comme ça:
<a class="tab {% ifequal active_tab "statistics" %}active{% endifequal %}" href="{% url Member.Statistics %}">Statistics</a>
et tout ce que je dois faire est à mon avis d'ajouter {'active_tab': 'statistics'}
à mon dictionnaire de contexte.
Si vous utilisez RequestContext
vous pouvez obtenir le chemin actuel dans votre modèle en tant que:
{{ request.path }}
Et à votre avis:
from Django.template import RequestContext
def my_view(request):
# do something awesome here
return template.render(RequestContext(request, context_dict))
J'ai pris le code de nivhab ci-dessus et enlevé un peu de wierdness et en ai fait un templatetag propre, je l'ai modifié pour que/account/edit/rende toujours/account/tab actif.
#current_nav.py
from Django import template
register = template.Library()
@register.tag
def current_nav(parser, token):
import re
args = token.split_contents()
template_tag = args[0]
if len(args) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
return NavSelectedNode(args[1])
class NavSelectedNode(template.Node):
def __init__(self, url):
self.url = url
def render(self, context):
path = context['request'].path
pValue = template.Variable(self.url).resolve(context)
if (pValue == '/' or pValue == '') and not (path == '/' or path == ''):
return ""
if path.startswith(pValue):
return ' class="current"'
return ""
#template.html
{% block nav %}
{% load current_nav %}
{% url home as home_url %}
{% url signup as signup_url %}
{% url auth_login as auth_login_url %}
<ul class="container">
<li><a href="{{ home_url }}"{% current_nav home_url %} title="Home">Home</a></li>
<li><a href="{{ auth_login_url }}"{% current_nav auth_login_url %} title="Login">Login</a></li>
<li><a href="{{ signup_url }}"{% current_nav signup_url %} title="Signup">Signup</a></li>
</ul>
{% endblock %}
Ceci est juste une variante de la solution CSS proposée par Toba ci-dessus:
Incluez les éléments suivants dans votre modèle de base:
<body id="section-{% block section %}home{% endblock %}">
Ensuite, dans vos modèles qui étendent l'utilisation de base:
{% block section %}show{% endblock %}
Vous pouvez ensuite utiliser css pour mettre en évidence la zone actuelle en fonction de la balise body (par exemple, si nous avons un lien avec un identifiant de nav-home):
#section-home a#nav-home{
font-weight:bold;
}
Merci pour vos réponses jusqu'à présent, messieurs. Je suis encore parti pour quelque chose de légèrement différent ..
Dans mon modèle:
<li{{ link1_active }}>...link...</li>
<li{{ link2_active }}>...link...</li>
<li{{ link3_active }}>...link...</li>
<li{{ link4_active }}>...link...</li>
Une fois que j'ai déterminé la page sur laquelle je me trouve dans la logique (généralement dans urls.py), je passe class="selected"
dans le cadre du contexte, sous le bon nom pour le modèle.
Par exemple, si je suis sur la page de lien1, je vais ajouter {'link1_active':' class="selected"'}
au contexte pour que le modèle soit récupéré et injecté.
Cela semble fonctionner et c'est assez propre.
Edit: pour garder le HTML en dehors de mon contrôleur/vue, j'ai un peu modifié ceci:
<li{% if link1_active %} class="selected"{% endif %}>...link...</li>
<li{% if link2_active %} class="selected"{% endif %}>...link...</li>
...
Cela rend le modèle un peu moins lisible, mais je suis d'accord, il est préférable de ne pas utiliser le code HTML brut à partir du fichier urls.
Vous pouvez utiliser la fonction reverse avec les paramètres appropriés pour obtenir l’URL actuelle.
J'ai plusieurs menus sur la même page qui sont créés dynamiquement à travers une boucle. Les messages ci-dessus relatifs au contexte m'ont fourni une solution rapide. J'espère que ça aide quelqu'un. (J'utilise cela en plus de la balise de modèle active - mon correctif résout le problème dynamique). Cela ressemble à une comparaison idiote, mais cela fonctionne. J'ai choisi de nommer les variables active_something-unique et quelque chose-unique, afin que cela fonctionne avec des menus imbriqués.
Voici une partie de la vue (assez pour comprendre ce que je fais):
def project_list(request, catslug):
"render the category detail page"
category = get_object_or_404(Category, slug=catslug, site__id__exact=settings.SITE_ID)
context = {
'active_category':
category,
'category':
category,
'category_list':
Category.objects.filter(site__id__exact=settings.SITE_ID),
}
Et cela provient du modèle:
<ul>
{% for category in category_list %}
<li class="tab{% ifequal active_category category %}-active{% endifequal %}">
<a href="{{ category.get_absolute_url }}">{{ category.cat }}</a>
</li>
{% endfor %}
</ul>
Une petite amélioration par rapport à @tback , sans les balises %if%
:
# navigation.py
from Django import template
from Django.core.urlresolvers import resolve
register = template.Library()
@register.filter(name="activate_if_active", is_safe=True)
def activate_if_active(request, urlname):
if resolve(request.get_full_path()).url_name == urlname:
return "active"
return ''
Utilisez-le dans votre modèle comme ça:
{% load navigation %}
<li class="{{ request|activate_if_active:'url_name' }}">
<a href="{% url 'url_name' %}">My View</a>
</li>
Et incluez "Django.core.context_processors.request"
dans votre réglage TEMPLATE_CONTEXT_PROCESSORS
.
J'ai trouvé le meilleur est d'utiliser une balise d'inclusion:
templates/fnf/nav_item.html
<li class="nav-item">
<a class="nav-link {% if is_active %}active{% endif %}" href="{% url url_name %}">{{ link_name }}</a>
</li>
Ceci est juste mon élément de base de navigation bootstrap que je souhaite rendre.
Il obtient la valeur href et éventuellement la valeur link_name. is_active
est calculé en fonction de la demande en cours.
templatetags/nav.py
from Django import template
register = template.Library()
@register.inclusion_tag('fnf/nav_item.html', takes_context=True)
def nav_item(context, url_name, link_name=None):
return {
'url_name': url_name,
'link_name': link_name or url_name.title(),
'is_active': context.request.resolver_match.url_name == url_name,
}
Puis utilisez-le dans un nav: templates/fnf/nav.html
{% load nav %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<ul class="navbar-nav mr-auto">
{% nav_item 'dashboard' %}
</ul>
J'ai utilisé jQuery pour mettre en évidence mes barres de navigation. Cette solution ajoute simplement la classe css "active" à l'élément qui correspond au sélecteur css.
<script type="text/javascript" src="/static/js/jquery.js"></script>
<script>
$(document).ready(function(){
var path = location.pathname;
$('ul.navbar a.nav[href$="' + path + '"]').addClass("active");
});
</script>
Ma solution consistait à écrire un processeur de contexte simple pour définir une variable en fonction du chemin de requête:
def navigation(request):
"""
Custom context processor to set the navigation menu pointer.
"""
nav_pointer = ''
if request.path == '/':
nav_pointer = 'main'
Elif request.path.startswith('/services/'):
nav_pointer = 'services'
Elif request.path.startswith('/other_stuff/'):
nav_pointer = 'other_stuff'
return {'nav_pointer': nav_pointer}
(N'oubliez pas d'ajouter votre processeur personnalisé à TEMPLATE_CONTEXT_PROCESSORS dans settings.py.)
Ensuite, dans le modèle de base, j'utilise une balise ifequal par lien pour déterminer s'il faut ajouter la classe "active". Certes, cette approche est strictement limitée à la flexibilité de votre structure de chemin, mais elle fonctionne pour mon déploiement relativement modeste.
Juste un autre progrès de la solution originale.
Ceci accepte plusieurs modèles et il vaut mieux également utiliser des modèles non nommés écrits sous forme d'URL relative, entourés de "" ", comme suit:
{% url admin:clients_client_changelist as clients %}
{% url admin:clients_town_changelist as towns %}
{% url admin:clients_district_changelist as districts %}
<li class="{% active "/" %}"><a href="/">Home</a></li>
<li class="{% active clients %}"><a href="{{ clients }}">Clients</a></li>
{% if request.user.is_superuser %}
<li class="{% active towns districts %}">
<a href="#">Settings</a>
<ul>
<li><a href="{{ towns }}">Towns</a></li>
<li><a href="{{ districts }}">Districts</a></li>
</ul>
</li>
{% endif %}
Tag va comme ça:
from Django import template
register = template.Library()
@register.tag
def active(parser, token):
args = token.split_contents()
template_tag = args[0]
if len(args) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
return NavSelectedNode(args[1:])
class NavSelectedNode(template.Node):
def __init__(self, urls):
self.urls = urls
def render(self, context):
path = context['request'].path
for url in self.urls:
if '"' not in url:
cpath = template.Variable(url).resolve(context)
else:
cpath = url.strip('"')
if (cpath == '/' or cpath == '') and not (path == '/' or path == ''):
return ""
if path.startswith(cpath):
return 'active'
return ""
Je voulais juste partager mon amélioration mineure au poste de nivhab. Dans mon application, j'ai des sous-navigations et je ne voulais pas les cacher en utilisant uniquement du CSS, il me fallait donc une sorte de balise "if" pour afficher la sous-navigation pour un élément ou non.
from Django import template
register = template.Library()
@register.tag
def ifnaviactive(parser, token):
nodelist = parser.parse(('endifnaviactive',))
parser.delete_first_token()
import re
args = token.split_contents()
template_tag = args[0]
if len(args) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
return NavSelectedNode(args[1:], nodelist)
class NavSelectedNode(template.Node):
def __init__(self, patterns, nodelist):
self.patterns = patterns
self.nodelist = nodelist
def render(self, context):
path = context['request'].path
for p in self.patterns:
pValue = template.Variable(p).resolve(context)
if path == pValue:
return self.nodelist.render(context)
return ""
Vous pouvez utiliser cela de la même manière que la balise active:
{% url product_url as product %}
{% ifnaviactive request product %}
<ul class="subnavi">
<li>Subnavi item for product 1</li>
...
</ul>
{% endifnaviactive %}
En modifiant légèrement la réponse d'Andreas, il semble que vous puissiez transmettre le nom de la route d'urls.py à la balise de modèle. Dans mon exemple my_tasks
, puis dans la fonction de balise de modèle, utilisez la fonction inverse pour déterminer l'URL à utiliser. Vous pouvez ensuite faire correspondre cette URL à l'URL de l'objet de requête (disponible dans le contexte du modèle)
from Django import template
from Django.core.urlresolvers import reverse
register = template.Library()
@register.tag
def active(parser, token):
args = token.split_contents()
template_tag = args[0]
if len(args) < 2:
raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
return NavSelectedNode(args[1:])
class NavSelectedNode(template.Node):
def __init__(self, name):
self.name = name
def render(self, context):
if context['request'].path == reverse(self.name[1]):
return 'active'
else:
return ''
urls.py
url(r'^tasks/my', my_tasks, name = 'my_tasks' ),
template.html
<li class="{% active request all_tasks %}"><a href="{% url all_tasks %}">Everyone</a></li>
Je sais que je suis en retard à la fête. Cependant, je n’ai aimé aucune des solutions populaires:
La méthode block semble fausse: je pense que la navigation devrait être autonome.
La méthode template_tag semble erronée: je n'aime pas cela, je dois d'abord obtenir l'URL du tag url. De plus, je pense que la classe css devrait être définie dans le modèle, pas dans la balise.
J'ai donc écrit un filtre qui ne présente pas les inconvénients décrits ci-dessus. Il retourne True
si une URL est active et peut donc être utilisé avec {% if %}
:
{% load navigation %}
<li{% if request|active:"home" %} class="active"{% endif %}><a href="{% url "home" %}">Home</a></li>
Le code:
@register.filter(name="active")
def active(request, url_name):
return resolve(request.path_info).url_name == url_name
Veillez simplement à utiliser RequestContext
sur les pages avec navigation ou à activer la requête context_processor dans votre settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
...
'Django.core.context_processors.request',
)
J'ai vu les réponses de jpwatts ', 110j , nivhab & Marcus Whybrow , mais elles semblent toutes manquer de quelque chose: que dire de la racine chemin ? Pourquoi est-il toujours actif?
Donc, j'ai fait un autre chemin, plus facile, qui permet au "contrôleur" de décider par lui-même et je pense que cela résout la plupart des gros problèmes.
Voici mon tag personnalisé:
## myapp_tags.py
@register.simple_tag
def nav_css_class(page_class):
if not page_class:
return ""
else:
return page_class
Ensuite, le "contrôleur" déclare les classes CSS nécessaires (en fait, le plus important est de déclarer sa présence au modèle)
## views.py
def ping(request):
context={}
context["nav_ping"] = "active"
return render(request, 'myapp/ping.html',context)
Et enfin, je le rends dans ma barre de navigation:
<!-- sidebar.html -->
{% load myapp_tags %}
...
<a class="{% nav_css_class nav_home %}" href="{% url 'index' %}">
Accueil
</a>
<a class="{% nav_css_class nav_candidats %}" href="{% url 'candidats' %}">
Candidats
</a>
<a class="{% nav_css_class nav_ping %}" href="{% url 'ping' %}">
Ping
</a>
<a class="{% nav_css_class nav_stat %}" href="{% url 'statistiques' %}">
Statistiques
</a>
...
Ainsi, chaque page a sa propre valeur nav_css_class
à définir et, si elle est définie, le modèle est rendu actif: aucun besoin de request
dans le contexte du modèle, aucune mise en page d'URL et plus de problèmes liés aux pages multi-URL ou aux pages racine.
de cette SO Question
{% url 'some_urlpattern_name' as url %}
<a href="{{url}}"{% if request.path == url %} class="active"{% endif %}>Link</a>
Répétez autant que nécessaire pour chaque lien.
voici une solution assez simple, https://github.com/hellysmile/Django-activeurl
Créez un modèle d'inclusion "intranet/nav_item.html":
{% load url from future %}
{% url view as view_url %}
<li class="nav-item{% ifequal view_url request.path %} current{% endifequal %}">
<a href="{{ view_url }}">{{ title }}</a>
</li>
Et l'inclure dans l'élément nav:
<ul>
{% include "intranet/nav_item.html" with view='intranet.views.home' title='Home' %}
{% include "intranet/nav_item.html" with view='crm.views.clients' title='Clients' %}
</ul>
Et vous devez ajouter ceci aux paramètres:
from Django.conf import global_settings
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
'Django.core.context_processors.request',
)
Le mien est un peu similaire à une autre approche JS déjà soumise .. juste sans jQuery ...
Disons que nous avons dans base.html ce qui suit:
<div class="pure-u-1 pure-menu pure-menu-open pure-menu-horizontal header" >
<ul class="">
<li id="home"><a href="{% url 'article:index' %}">Home</a></li>
<li id="news"><a href="{% url 'article:index' %}">News</a></li>
<li id="analysis"><a href="{% url 'article:index' %}">Analysis</a></li>
<li id="opinion"><a href="{% url 'article:index' %}">Opinion</a></li>
<li id="data"><a href="{% url 'article:index' %}">Data</a></li>
<li id="events"><a href="{% url 'article:index' %}">Events</a></li>
<li id="forum"><a href="{% url 'article:index' %}">Forum</a></li>
<li id="subscribe"><a href="{% url 'article:index' %}">Subscribe</a></li>
</ul>
<script type="text/javascript">
(function(){
loc=/\w+/.exec(window.location.pathname)[0];
el=document.getElementById(loc).className='pure-menu-selected';
})();
</script>
</div>
Je viens de faire ma hiérarchie pour suivre un certain modèle d'URL ... après l'adresse de l'hôte ... j'ai ma catégorie principale, par exemple, la maison, les nouvelles, l'analyse, etc. et la regex tire juste le premier mot de l'emplacement
Voici mon coup d'oeil. J'ai fini par implémenter une classe dans mes vues contenant la structure de navigation (à plat avec des métadonnées). Je l'injecte ensuite dans le modèle et le rende.
Ma solution concerne i18n. Cela devrait probablement être un peu plus abstrait, mais je ne m'en suis pas vraiment préoccupé.
views.py:
from Django.utils.translation import get_language, ugettext as _
class Navi(list):
items = (_('Events'), _('Users'), )
def __init__(self, cur_path):
lang = get_language()
first_part = '/' + cur_path.lstrip('/').split('/')[0]
def set_status(n):
if n['url'] == first_part:
n['status'] == 'active'
for i in self.items:
o = {'name': i, 'url': '/' + slugify(i)}
set_status(o)
self.append(o)
# remember to attach Navi() to your template context!
# ie. 'navi': Navi(request.path)
J'ai défini la logique du modèle en utilisant include comme ceci. Modèle de base:
{% include "includes/navigation.html" with items=navi %}
Inclusion réelle (inclut/navigation.html):
<ul class="nav">
{% for item in items %}
<li class="{{ item.status }}">
<a href="{{ item.url }}">{{ item.name }}</a>
</li>
{% endfor %}
</ul>
Espérons que quelqu'un trouvera cela utile! Je suppose qu'il serait assez facile d'étendre cette idée pour prendre en charge les hiérarchies imbriquées, etc.
Inspiré par cette solution , j'ai commencé à utiliser cette approche:
**Placed in templates as base.html**
{% block tab_menu %}
<ul class="tab-menu">
<li class="{% if active_tab == 'tab1' %} active{% endif %}"><a href="#">Tab 1</a></li>
<li class="{% if active_tab == 'tab2' %} active{% endif %}"><a href="#">Tab 2</a></li>
<li class="{% if active_tab == 'tab3' %} active{% endif %}"><a href="#">Tab 3</a></li>
</ul>
{% endblock tab_menu %}
**Placed in your page template**
{% extends "base.html" %}
{% block tab_menu %}
{% with active_tab="tab1" %} {{ block.super }} {% endwith %}
{% endblock tab_menu %}
J'ai également utilisé jQuery pour le mettre en évidence et le trouver plus élégant que d'encombrer le modèle avec des balises de modèle Django non sémantiques.
Le code ci-dessous fonctionne avec les listes déroulantes imbriquées dans bootstrap 3 (met en surbrillance à la fois l'élément parent et l'élément enfant <li>
.
// DOM Ready
$(function() {
// Highlight current page in nav bar
$('.nav, .navbar-nav li').each(function() {
// Count the number of links to the current page in the <li>
var matched_links = $(this).find('a[href]').filter(function() {
return $(this).attr('href') == window.location.pathname;
}).length;
// If there's at least one, mark the <li> as active
if (matched_links)
$(this).addClass('active');
});
});
Il est également très facile d'ajouter un événement click
à return false
(ou de modifier l'attribut href
en #
) pour la page en cours, sans modifier le balisage template/html:
var matched_links = $(this).find('a[href]').filter(function() {
var matched = $(this).attr('href') == window.location.pathname;
if (matched)
$(this).click(function() { return false; });
return matched;
}).length;
J'utilise une combinaison de ce mixin pour les vues basées sur les classes:
class SetActiveViewMixin(object):
def get_context_data(self, **kwargs):
context = super(SetActiveViewMixin, self).get_context_data(**kwargs)
context['active_nav_menu'] = {
self.request.resolver_match.view_name: ' class="pure-menu-selected"'
}
return context
avec ceci dans le modèle:
<ul>
<li{{active_nav_menu.node_Explorer }}><a href="{% url 'node_Explorer' '' %}">Explore</a></li>
<li{{active_nav_menu.node_create }}><a href="{% url 'node_create' path %}">Create</a></li>
<li{{active_nav_menu.node_edit }}><a href="{% url 'node_edit' path %}">Edit</a></li>
<li{{active_nav_menu.node_delete }}><a href="{% url 'node_delete' path %}">Delete</a></li>
</ul>