Ich habe gerade meine erste kleine Webapp in Django gemacht und ich liebe es. Ich bin dabei, eine alte PHP-Produktionssite in Django zu konvertieren, und als Teil ihrer Vorlage gibt es eine Navigationsleiste.
In PHP überprüfe ich die URL jeder Navigationsoption mit der aktuellen URL im Vorlagencode und wende eine CSS-Klasse an, wenn sie ausgerichtet sind. Es ist schrecklich chaotisch.
Gibt es etwas Besseres für Django oder eine gute Möglichkeit, mit dem Code in der Vorlage umzugehen?
Wie würde ich zunächst die aktuelle URL abrufen?
django
navigation
Oli
quelle
quelle
<a href="{% url "view:name" %}" {% active_class "view:name" %}>
. Sie können es optional verwenden, um nur den" active"
Wert zu generieren (indem Sie ihnFalse
als zweites Argument an das Tag übergeben), um ihn an ein vorhandenes Klassenattribut anzuhängen. Für die meisten Navigationslinks verwende ich dieses Beispiel.Antworten:
Ich verwende die Vorlagenvererbung, um die Navigation anzupassen. Beispielsweise:
base.html
about.html
quelle
<ul id="nav">....</ul>
in eine andere Datei umgestaltet , sagen wir tabs.html. Jetzt ist base.html enthalten{%block nav%}{%include "tabs.html"%}{%endblock%}
und das Hervorheben der aktiven Registerkarte funktioniert nicht mehr (in about.html oben). Vermisse ich etwasinclude
Tag funktioniert. Schauen Sie sich die Notiz in der Dokumentation enthalten: docs.djangoproject.com/en/dev/ref/templates/builtins/#include In Ihrem Fall durch die Zeit , Sie versuchen , die Basisvorlage außer Kraft zu setzen inabout.html
, ich glaube , Sie haben Ich habe bereits einen gerenderten HTML-Block anstelle eines Django-Vorlagenblocks, der darauf wartet, verarbeitet zu werden.Sie brauchen kein Wenn, um das zu tun, schauen Sie sich den folgenden Code an:
tags.py
urls.py
base.html
das ist es. Einzelheiten zur Implementierung finden Sie unter:
gnuvince.wordpress.com
110j.wordpress.com
quelle
django.core.context_processors.request
IhremTEMPLATE_CONTEXT_PROCESSORS
insettings.py
mysite.com
(als Heimat) undmysite.com/blog
, wie der Pfad zeigt,/
bzw./blog/
(bzw.) die jeweils eine Übereinstimmung für den ersteren ergeben. Wenn Sie nicht/
als Landung verwenden, ist dies möglicherweise in Ordnung, andernfalls verwende ich nurreturn 'active' if pattern == request.path else ''
(ich habe noch keine Probleme damit gesehen, aber ich habe mich nur damit eingerichtet).Ich mochte die Sauberkeit von 110j oben, also nahm ich das meiste davon und überarbeitete, um die 3 Probleme zu lösen, die ich damit hatte:
Hier ist es:
tags.py:
urls.py:
base.html:
quelle
Ich bin der Autor der Django-Linie, die ich speziell geschrieben habe, um diese Frage zu lösen: D.
Ich ärgerte mich über die (vollkommen akzeptable) jpwatts-Methode in meinen eigenen Projekten und ließ mich von 110js Antwort inspirieren. Die Abstammung sieht folgendermaßen aus:
ancestor
wird einfach durch "aktiv" ersetzt, wenn das Argument mit dem Anfang der aktuellen Seiten-URL übereinstimmt.Variable Argumente und die vollständige
{% url %}
umgekehrte Auflösung werden ebenfalls unterstützt. Ich habe ein paar Konfigurationsoptionen eingestreut und es ein wenig ausgearbeitet und für alle verpackt.Wenn jemand interessiert ist, lesen Sie ein bisschen mehr darüber unter:
>> github.com/marcuswhybrow/django-lineage
quelle
Seit Django 1.5 :
Wenn Sie solche Ansichten verwenden, können Sie etwas Ähnliches
breadcrumbs
als Feld auf Klassenebene hinzufügen und in Ihren Vorlagen verwenden.Beispielansichtscode:
In Ihrer Vorlage können Sie sie folgendermaßen verwenden:
Wenn Sie übergeordnete Navigationselemente zusätzlich "hervorheben" möchten, müssen Sie die
breadcrumbs
Liste erweitern:... und in Ihrer Vorlage:
Dies ist eine einfache und saubere Lösung und funktioniert ziemlich gut mit verschachtelter Navigation.
quelle
.active
?breadcrumbs
wenn Sie möchten. Aber Sie haben Recht - mein Beispiel ist nicht das beste.Sie können eine Klasse oder ID auf das Hauptelement der Seite und nicht auf ein bestimmtes Navigationselement anwenden.
HTML:
CSS:
quelle
So mach ich es:
und dann muss ich aus meiner Sicht nur noch
{'active_tab': 'statistics'}
zu meinem Kontextwörterbuch hinzufügen .Wenn Sie verwenden
RequestContext
, können Sie den aktuellen Pfad in Ihrer Vorlage wie folgt abrufen:Und aus Ihrer Sicht:
quelle
Ich nahm den Code von nivhab oben und entfernte etwas Seltsamkeit und machte ihn zu einem sauberen Templatetag, modifizierte ihn so, dass / account / edit / / account / tab weiterhin aktiv macht.
quelle
Dies ist nur eine Variante der oben von Toba vorgeschlagenen CSS-Lösung:
Nehmen Sie Folgendes in Ihre Basisvorlage auf:
Dann in Ihren Vorlagen, die die Basis erweitern, verwenden Sie:
Sie können dann CSS verwenden, um den aktuellen Bereich basierend auf dem Body-Tag hervorzuheben (z. B. wenn wir einen Link mit der ID nav-home haben):
quelle
Sie können die Umkehrfunktion mit den entsprechenden Parametern verwenden, um die aktuelle URL abzurufen.
quelle
Vielen Dank für Ihre bisherigen Antworten, Herren. Ich habe mich wieder für etwas anderes entschieden.
In meiner Vorlage:
Sobald ich herausgefunden habe, auf welcher Seite ich mich in der Logik befinde (normalerweise in urls.py), übergebe ich
class="selected"
als Teil des Kontexts unter dem richtigen Namen die Vorlage.Wenn ich beispielsweise auf der Seite link1 bin, werde ich anhängen
{'link1_active':' class="selected"'}
den Kontext , damit die Vorlage aufgenommen und injiziert werden kann.Es scheint zu funktionieren und ist ziemlich sauber.
Bearbeiten: Um HTML von meinem Controller / meiner Ansicht fernzuhalten, habe ich dies ein wenig geändert:
Es macht die Vorlage etwas weniger lesbar, aber ich stimme zu, es ist besser, nicht rohen HTML-Code aus der URL-Datei zu pushen.
quelle
Ich habe mehrere Menüs auf derselben Seite, die dynamisch über eine Schleife erstellt werden. Die obigen Beiträge zum Kontext gaben mir eine schnelle Lösung. Hoffe das hilft jemandem. (Ich verwende dies zusätzlich zum aktiven Vorlagen-Tag - mein Fix löst das dynamische Problem). Es scheint ein dummer Vergleich zu sein, aber es funktioniert. Ich habe mich entschieden, die Variablen active_something-unique und etwas-unique zu benennen. Auf diese Weise funktioniert es mit verschachtelten Menüs.
Hier ist ein Teil der Ansicht (genug, um zu verstehen, was ich tue):
Und das ist aus der Vorlage:
quelle
Meine Lösung bestand darin, einen einfachen Kontextprozessor zu schreiben, um eine Variable basierend auf dem Anforderungspfad festzulegen:
(Vergessen Sie nicht, Ihren benutzerdefinierten Prozessor in settings.py zu TEMPLATE_CONTEXT_PROCESSORS hinzuzufügen.)
Dann verwende ich in der Basisvorlage ein ifequal-Tag pro Link, um zu bestimmen, ob die "aktive" Klasse angehängt werden soll. Zugegeben, dieser Ansatz ist streng auf die Flexibilität Ihrer Pfadstruktur beschränkt, funktioniert jedoch für meine relativ bescheidene Bereitstellung.
quelle
Ich wollte nur meine kleine Verbesserung von Nivhabs Post teilen. In meiner Anwendung habe ich Subnavigationen und ich wollte sie nicht nur mit CSS ausblenden, daher brauchte ich eine Art "if" -Tag, um die Subnavigation für ein Element anzuzeigen oder nicht.
Sie können dies grundsätzlich genauso verwenden wie das aktive Tag:
quelle
Nur eine weitere Verbesserung der ursprünglichen Lösung.
Dies akzeptiert mehrere Muster und am besten auch unbenannte Muster, die als relative URL in '"' geschrieben sind, wie folgt:
Tag geht so:
quelle
Ich habe jquery verwendet, um meine Navigationsleisten hervorzuheben. Diese Lösung fügt einfach die CSS-Klasse "aktiv" zu dem Element hinzu, das zum CSS-Selektor passt.
quelle
Eine kleine Verbesserung gegenüber der Antwort von @tback ohne
%if%
Tags:Verwenden Sie es in Ihrer Vorlage wie folgt:
Und
"django.core.context_processors.request"
in IhreTEMPLATE_CONTEXT_PROCESSORS
Einstellung aufnehmen.quelle
Ich fand es am besten, ein Einschluss-Tag zu verwenden:
templates/fnf/nav_item.html
Dies ist nur mein grundlegendes Bootstrap-Navigationselement, das ich rendern möchte.
Es erhält den href-Wert und optional den link_name-Wert.
is_active
wird basierend auf der aktuellen Anfrage berechnet.templatetags/nav.py
Dann verwenden Sie es in einem Navi:
templates/fnf/nav.html
quelle
/about/company-history/
oder/about/what-we-do/
is_active
kann aber ersetzt und andere Schlüssel zum Wörterbuch zurückgegeben werden. Auch der Scheck kann seincontext.request.resolver_match.url_name.startswith(x)
oder irgendetwas anderes. Sie können auch Code vor der return-Anweisung haben, um die dict-Werte festzulegen. Sie können auch verschiedene Vorlagen verwenden, dh eine fürtop_level_nav.html
mit unterschiedlicher Logik usw.Wenn Sie die Antwort von Andreas leicht ändern, können Sie den Namen der Route von urls.py an das Vorlagen-Tag übergeben. In meinem Beispiel
my_tasks
und dann in der Vorlagen-Tag-Funktion verwenden Sie die Umkehrfunktion, um herauszufinden, wie die URL lauten soll. Dann können Sie diese mit der URL im Anforderungsobjekt abgleichen (verfügbar im Vorlagenkontext).urls.py
template.html
quelle
Ich weiß, dass ich zu spät zur Party komme. Ich mochte jedoch keine der beliebten Lösungen:
Die Blockmethode scheint falsch zu sein: Ich denke, die Navigation sollte in sich geschlossen sein.
Die template_tag-Methode scheint falsch zu sein: Ich mag es nicht, dass ich zuerst die URL vom URL-Tag abrufen muss. Ich denke auch, dass die CSS-Klasse in der Vorlage definiert werden sollte, nicht im Tag.
Ich habe daher einen Filter geschrieben, der nicht die oben beschriebenen Nachteile aufweist. Es wird zurückgegeben,
True
wenn eine URL aktiv ist, und kann daher verwendet werden mit{% if %}
:Der Code:
RequestContext
Stellen Sie einfach sicher, dass Sie auf Seiten mit Navigation verwenden oder die Anforderung context_processor in Ihrem aktivierensettings.py
quelle
Ich habe jpwatts ', 110j ' s, nivhab 's und Marcus Whybrow gesehen , aber allen scheint etwas zu fehlen: Was ist mit dem Wurzelpfad? Warum ist es immer aktiv?
Also habe ich einen anderen Weg einfacher gemacht, der den "Controller" dazu bringt, selbst zu entscheiden, und ich denke, er löst die meisten großen Probleme.
Hier ist mein benutzerdefiniertes Tag:
Dann deklariert der "Controller" die benötigten CSS-Klassen (am wichtigsten ist, dass er der Vorlage seine Anwesenheit deklariert).
Und schließlich rendere ich es in meiner Navigationsleiste:
Daher muss für jede Seite ein eigener
nav_css_class
Wert festgelegt werden. Wenn diese festgelegt ist, wird die Vorlage aktiv: Keine Notwendigkeitrequest
im Vorlagenkontext, kein URL-Parcing und keine Probleme mehr mit Seiten mit mehreren URLs oder Stammseiten.quelle
Inspiriert von dieser Lösung begann ich, diesen Ansatz zu verwenden:
quelle
Hier ist mein Versuch. Am Ende habe ich eine Klasse in meinen Ansichten implementiert, die meine Navigationsstruktur enthält (flach mit einigen Metadaten). Ich füge dies dann in die Vorlage ein und rendere es aus.
Meine Lösung befasst sich mit i18n. Es sollte wahrscheinlich ein bisschen mehr abstrahiert werden, aber das hat mich nicht wirklich gestört.
views.py:
Ich habe die Vorlagenlogik mit solchen Includes definiert. Basisvorlage:
Tatsächliches Include (Includes / Navigation.html):
Hoffentlich findet das jemand nützlich! Ich denke, es wäre ziemlich einfach, diese Idee zu erweitern, um verschachtelte Hierarchien usw. zu unterstützen.
quelle
Erstellen Sie eine Include-Vorlage "intranet / nav_item.html":
Und fügen Sie es in das nav-Element ein:
Und Sie müssen dies zu den Einstellungen hinzufügen:
quelle
Hier ist eine ziemlich einfache Lösung: https://github.com/hellysmile/django-activeurl
quelle
von dieser SO Frage
Wiederholen Sie diesen Vorgang nach Bedarf für jeden Link.
quelle
/blog/posts/2021/04/12
die URL ist der / Blog / nav Artikel würde aktiv sein.Questions
,Tags
,Users
,Badges
,Unanswered
,Ask Question
. es wird nicht funktionierenQuestions
, aber für alle anderen Navis wird es gut funktionieren.Ich habe jQuery auch verwendet, um es hervorzuheben und eleganter zu finden, als die Vorlage mit nicht-semantischen Django-Vorlagen-Tags zu überladen.
Der folgende Code funktioniert mit verschachtelten Dropdowns in Bootstrap 3 (hebt sowohl das übergeordnete als auch das untergeordnete
<li>
Element hervor.Es ist auch ganz einfach, der aktuellen Seite ein
click
Ereignis hinzuzufügenreturn false
(oder dashref
Attribut in zu ändern#
), ohne das Vorlagen- / HTML-Markup zu ändern:quelle
Ich verwende eine Kombination dieses Mixins für klassenbasierte Ansichten:
mit diesem in der Vorlage:
quelle
Meins ähnelt ein bisschen einem anderen JS-Ansatz, der zuvor eingereicht wurde. Nur ohne jQuery ...
Angenommen, wir haben in base.html Folgendes:
Ich habe gerade meine Hierarchie so gestaltet, dass sie einem bestimmten URL-Muster folgt ... nach der Hostadresse ... ich habe meine Hauptkategorie, z. B. Startseite, Nachrichten, Analyse usw., und der reguläre Ausdruck zieht nur das erste Wort aus dem Speicherort
quelle