Je viens de faire ma première petite application web dans django et j'adore ça. Je suis sur le point de commencer à convertir un ancien site PHP de production en django et dans le cadre de son modèle, il y a une barre de navigation.
En PHP, je vérifie l'URL de chaque option de navigation par rapport à l'URL actuelle, dans le code du modèle et j'applique une classe CSS si elles s'alignent. C'est horriblement désordonné.
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 procéder pour obtenir l'URL actuelle?
<a href="{% url "view:name" %}" {% active_class "view:name" %}>
. Vous pouvez éventuellement l'utiliser pour générer uniquement la" active"
valeur (en la passantFalse
comme deuxième argument à la balise) à ajouter à un attribut de classe existant, mais pour la plupart des liens de navigation, cet exemple est ce que j'utilise.Réponses:
J'utilise l'héritage de modèle pour personnaliser la navigation. Par exemple:
base.html
about.html
la source
<ul id="nav">....</ul>
dans un fichier différent, disons tabs.html. Alors maintenant, base.html contenu{%block nav%}{%include "tabs.html"%}{%endblock%}
, puis la mise en évidence de l'onglet actif a cessé de fonctionner (dans about.html ci-dessus). Est-ce que je manque quelque chose?include
tag. Consultez la note incluse dans la documentation: docs.djangoproject.com/en/dev/ref/templates/builtins/#include Dans votre cas, au moment où vous essayez de remplacer le modèle de base dansabout.html
, je pense que vous a déjà un bloc HTML rendu, plutôt qu'un bloc de modèle Django en attente de traitement.Vous n'avez pas besoin d'un if pour le faire, jetez un œil au code suivant:
tags.py
urls.py
base.html
c'est tout. pour plus de détails sur l'implémentation, consultez:
gnuvince.wordpress.com
110j.wordpress.com
la source
django.core.context_processors.request
à votreTEMPLATE_CONTEXT_PROCESSORS
insettings.py
mysite.com
(comme home) etmysite.com/blog
, comme le chemin apparaîtra comme/
et/blog/
(respectivement) donnant une correspondance pour le premier à chaque fois. Si vous ne l'utilisez pas/
comme atterrissage, cela peut convenir sinon j'utilise simplementreturn 'active' if pattern == request.path else ''
(je n'ai pas encore vu de problèmes avec cela, mais je viens de configurer en utilisant cela).J'ai aimé la propreté du 110j ci-dessus, alors j'en ai pris la majeure partie et je l'ai refactorisé pour résoudre les 3 problèmes que j'avais avec:
C'est ici:
tags.py:
urls.py:
base.html:
la source
Je suis l'auteur de django-lineage que j'ai écrit spécifiquement pour résoudre cette question: D
Je suis devenu ennuyé 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:
ancestor
est simplement remplacé par "active" si l'argument correspond au début de l'URL de la page courante.Les arguments variables et
{% url %}
la résolution inverse de type complet sont également pris en charge. J'ai saupoudré quelques options de configuration, je l'ai un peu étoffé et je l'ai emballé pour que tout le monde puisse l'utiliser.Si quelqu'un est intéressé, lisez un peu plus à ce sujet sur:
>> github.com/marcuswhybrow/django-lineage
la source
Depuis Django 1.5 :
Donc, si vous utilisez de telles vues, vous pouvez ajouter quelque chose de similaire en
breadcrumbs
tant que champ de niveau de classe et l'utiliser dans vos modèles.Exemple de code de vue:
Dans votre modèle, vous pouvez l'utiliser de cette manière:
Si vous souhaitez également "mettre en évidence" les éléments de navigation parents, vous devez étendre la
breadcrumbs
liste:... et dans votre modèle:
C'est une solution simple et propre qui fonctionne plutôt bien avec la navigation imbriquée.
la source
.active
?breadcrumbs
si vous le souhaitez. Mais vous avez raison - mon exemple n'est pas le meilleur.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:
CSS:
la source
Je le fais comme ça:
et ensuite tout ce que j'ai à faire est à mon avis d'ajouter
{'active_tab': 'statistics'}
à mon dictionnaire contextuel.Si vous utilisez,
RequestContext
vous pouvez obtenir le chemin actuel dans votre modèle sous la forme:Et à votre avis:
la source
J'ai pris le code de nivhab ci-dessus et j'ai supprimé certaines bizarreries et en ai fait un templatetag propre, je l'ai modifié pour que / account / edit / rende toujours / account / tab actif.
la source
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:
Puis dans vos modèles qui étendent l'utilisation de base:
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):
la source
Vous pouvez utiliser la fonction inverse avec les paramètres appropriés pour obtenir l'url actuelle.
la source
Merci pour vos réponses jusqu'à présent, messieurs. J'ai encore opté pour quelque chose de légèrement différent.
Dans mon modèle:
Une fois que j'ai déterminé sur quelle page je me trouve dans la logique (généralement dans urls.py), je passe
class="selected"
dans le contexte sous le bon nom au modèle.Par exemple, si je suis sur la page link1, j'ajouterai
{'link1_active':' class="selected"'}
au contexte pour que le modèle récupère et injecte.Cela semble fonctionner et c'est assez propre.
Edit: pour garder HTML hors de mon contrôleur / vue, j'ai un peu modifié ceci:
Cela rend le modèle un peu moins lisible, mais je suis d'accord, il vaut mieux ne pas pousser le HTML brut à partir du fichier urls.
la source
J'ai plusieurs menus sur la même page qui sont créés dynamiquement via une boucle. Les messages ci-dessus relatifs au contexte m'ont donné une solution rapide. J'espère que cela aide quelqu'un. (J'utilise ceci en plus de la balise de modèle active - mon correctif résout le problème dynamique). Cela semble être une comparaison idiote, mais cela fonctionne. J'ai choisi de nommer les variables active_something-unique et something-unique, de cette façon cela fonctionne avec des menus imbriqués.
Voici une partie de la vue (assez pour comprendre ce que je fais):
Et cela provient du modèle:
la source
Ma solution était d'écrire un processeur de contexte simple pour définir une variable en fonction du chemin de la requête:
(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 la structure de votre chemin, mais cela fonctionne pour mon déploiement relativement modeste.
la source
Je voulais juste partager ma petite amélioration apportée à la publication de nivhab. Dans mon application, j'ai des sous-navigations et je ne voulais pas les cacher en utilisant uniquement du CSS, donc j'avais besoin d'une sorte de balise "if" pour afficher la sous-navigation d'un élément ou non.
Vous pouvez l'utiliser fondamentalement de la même manière que la balise active:
la source
Juste une autre évolution de la solution originale.
Cela accepte plusieurs modèles et ce qui est mieux également les modèles sans nom écrits sous forme d'URL relative encapsulée dans '"', comme suit:
La balise va comme ceci:
la source
J'ai utilisé jquery pour mettre en évidence mes navbars. Cette solution ajoute simplement la classe css "active" à l'élément qui correspond au sélecteur css.
la source
Une petite amélioration par rapport à la réponse de @tback , sans aucun
%if%
tag:Utilisez-le dans votre modèle comme ça:
Et incluez
"django.core.context_processors.request"
dans votreTEMPLATE_CONTEXT_PROCESSORS
cadre.la source
J'ai trouvé que le mieux est d'utiliser une balise d'inclusion:
templates/fnf/nav_item.html
C'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
Ensuite, utilisez-le dans un nav:
templates/fnf/nav.html
la source
/about/company-history/
ou/about/what-we-do/
is_active
peut être remplacé et d'autres clés ajoutées au dictionnaire renvoyées. En outre, le chèque peut êtrecontext.request.resolver_match.url_name.startswith(x)
ou quoi que ce soit d'autre. En outre, vous pouvez avoir du code avant l'instruction return afin d'établir les valeurs dict. En outre, vous pouvez utiliser différents modèles, c'est-à-dire un pourtop_level_nav.html
avec une logique différente, etc.En modifiant légèrement la réponse d'Andreas, il semble que vous puissiez passer le nom de la route de 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 ce que devrait être l'URL, puis vous pouvez la faire correspondre à l'URL dans l'objet de requête (disponible dans le contexte du modèle)urls.py
template.html
la source
Je sais que je suis en retard à la fête. Cependant, je n'ai aimé aucune des solutions populaires:
La méthode de blocage semble erronée: je pense que la navigation devrait être autonome.
La méthode template_tag semble incorrecte: je n'aime pas le fait que je doive d'abord obtenir l'url de la balise 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 que j'ai décrits ci-dessus. Il retourne
True
si une url est active et peut donc être utilisée avec{% if %}
:Le code:
Assurez-vous simplement de l'utiliser
RequestContext
sur les pages avec navigation ou d'activer la requête context_processor dans votresettings.py
la source
J'ai vu les réponses de jpwatts , 110j , nivhab et Marcus Whybrow , mais elles semblent toutes manquer de quelque chose: qu'en est-il du chemin racine? Pourquoi est-ce toujours actif?
J'ai donc fait un autre moyen, plus facile, qui fait que le "contrôleur" décide par lui-même et je pense que cela résout la plupart des gros problèmes.
Voici mon tag personnalisé:
Ensuite, le "contrôleur" déclare les classes CSS nécessaires (en fait, le plus important est qu'il déclare sa présence au modèle)
Et enfin, je le rende dans ma barre de navigation:
Ainsi, chaque page a sa propre
nav_css_class
valeur à définir, et si elle est définie, le modèle est rendu actif: pas besoin derequest
contexte de modèle, pas de parcage d'URL et plus de problèmes de pages multi-URL ou de page racine.la source
Inspiré par cette solution , j'ai commencé à utiliser cette approche:
la source
Voici mon essai. J'ai fini par implémenter une classe dans mes vues qui contient ma structure de navigation (plate avec quelques métadonnées). Je l'injecte ensuite dans le modèle et le rend.
Ma solution concerne i18n. Cela devrait probablement être un peu plus abstrait, mais cela ne me dérange pas vraiment.
views.py:
J'ai défini la logique du modèle en utilisant des inclusions comme celle-ci. Modèle de base:
Inclure réel (includes / navigation.html):
J'espère 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.
la source
Créez un modèle d'inclusion "intranet / nav_item.html":
Et incluez-le dans l'élément nav:
Et vous devez ajouter ceci aux paramètres:
la source
voici une solution assez simple, https://github.com/hellysmile/django-activeurl
la source
de cette question SO
Répétez au besoin pour chaque lien.
la source
/blog/posts/2021/04/12
c'était l'URL, l'élément / blog / nav serait actif.Questions
,Tags
,Users
,Badges
,Unanswered
,Ask Question
. cela ne fonctionnera pas pourQuestions
, mais pour tous les autres navs, cela fonctionnera bien.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 évidence à la fois le parent et l'
<li>
élément enfant .Il est également assez facile d'ajouter un
click
événement àreturn false
(ou de modifier l'href
attribut en#
) pour la page actuelle, sans changer le balisage template / html:la source
J'utilise une combinaison de ce mixin pour les vues basées sur les classes:
avec ceci dans le modèle:
la source
La mienne est un peu similaire à une autre approche JS soumise précédemment .. juste sans jQuery ...
Disons que nous avons dans base.html ce qui suit:
Je viens de faire en sorte que ma hiérarchie suive un certain modèle d'URL ... après l'adresse de l'hôte ... j'ai ma catégorie principale, par exemple, maison, actualités, analyse, etc. et l'expression régulière tire juste le premier mot de l'emplacement
la source