5

Ich möchte die aktuelle Seite im Navigationsmenü hervorheben. Offensichtlich muss ich den Menülinks eine Klasse wie "aktiv" geben, wenn Sie auf ihrer Seite sind. Dies ist ein klassisches Problem und ich habe viele Lösungen proposed gesehen. Mein Problem ist, dass ich alle hasse und keine davon für sehr TROCKEN halte. Zum Beispiel:Warum muss ich in all meinen Antworten RequestContext übergeben?

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

---- 

{% load tags %} 
<div id="navigation"> 
    <a class="{% active request "^/about/" %}" href="/about/">About</a> 
    <a class="{% active request "^/contact/" %}" href="/contact/">Contact</a> 
    <a class="{% active request "^/services/" %}" href="/services/">Services</a> 
</div> 

Der Tag nach Ihrer aktuellen Anfrage und eine URL Ausdruck und gibt ‚aktiv‘, wenn Sie zur Zeit auf dieser Seite sind. Alternativ kann dies mit benannten Ansichten anstelle von URLs gemacht werden, aber das Prinzip ist das gleiche.

Mein Hauptproblem dabei ist, dass meine Navigation auf 99% meiner Ansichten und noch genannt werden, um die aktuelle Anforderung variabel zu bekommen Ich habe noch einen Request auf die Vorlage mit so etwas wie diesem analysiert:

def contact(request): 
    # snip ... 
    return render_to_response(
       'contact.html', 
       { 'myvar' : myvar }, 
       context_instance=RequestContext(request)) 

Warum muss ich diese context_instance-Zeile zu jeder meiner Ansichten hinzufügen, wenn wahrscheinlich alle bis auf eine die Anforderungsvariable benötigt, um die aktuelle URL/Ansicht zur Hervorhebung der aktiven Verknüpfung zu erhalten? Das scheint furchtbar nass zu sein, vor allem für ein Feature, das in den allermeisten Django-Sites enthalten sein muss. Ich möchte, dass die Anfrage standardmäßig eingefügt wird und sie optional unterdrücken kann. Ich kann keine Möglichkeit finden, dies in der Middleware zu tun, da ich die Vorlage vor dem Rendern nicht abfangen kann, nachdem die Ansicht sie zurückgegeben hat.

Irgendwelche Vorschläge?

Antwort

16

Ihre Absicht ist sinnvoll, Sie benötigen die RequestContext die meiste Zeit und nur selten kann es aus Leistungsgründen sicher weggelassen werden. Die Lösung ist einfach, statt render_to_response Verwendung direct_to_template Abkürzung

from django.views.generic.simple import direct_to_template 

def contact(request): 
    # snip ... 
    return direct_to_template(request, 'contact.html', { 'myvar' : myvar }) 

... oder render_to Dekorateur aus django-annoying:

from annoying.decorators import render_to 

@render_to('template.html') 
def foo(request):   
    bar = Bar.object.all() 
    return {'bar': bar}  
+1

Der @render_to Dekorateur ist brilliant! Vielen Dank! – Jimmy

+0

+1 für die Empfehlung von @render_to! Beachten Sie, dass [django-nervous] (https://github.com/skorokithakis/django-annoying) aufgrund von Inaktivität übernommen und verschoben wurde. – antiplex

+2

4 Jahre später, und Django 1.5 hat die 'direct_to_template' entfernt. Was wäre nun der empfohlene Weg dafür, ohne Django-nervig zu benutzen – Patrick

1

Sie müssen dem Markup Ihrer Navigation nicht unbedingt etwas hinzufügen, um dem aktuellen einen anderen Stil zu geben - es gibt deklarative Möglichkeiten, dies mit CSS zu tun.

Siehe meine Antwort hier: Django: Is there a better way to bold the current page link für ein Beispiel.

+0

Die Benennung Ihrer Seiten mit Body-IDs ist eine gute Idee, aber das Body-Tag und die Navigation befinden sich in einer Basisvorlage. Ich könnte es blockieren und * {% block body_id%} my-page {% endblock%} * zu jeder Erweiterungsvorlage hinzufügen, aber wieder, wo ist der DRY? Gibt es eine Möglichkeit, dies zu automatisieren? Ich möchte entweder die benannte Ansicht als Body ID verwenden oder slugify oder etwas, anstatt sie explizit benennen zu müssen und zwei separate "Namen" für jede Ansicht zu pflegen: eine für die Ansicht selbst und eine für die CSS-ID. – Jimmy

+0

Mein Django-fu ist rostig, aber anstatt jede Erweiterungsvorlage zu ändern, könnten Sie den CSS-Namen von contact() und family eingeben: def contact (request): render_to_response ('contact.html', {'cssClass': ' Kontaktseite ',' Myvar ': Myvar}, ...)? Immer noch nicht perfekt trocken, aber nicht schlecht. – RichieHindle

0

Für die Zukunft, ein django-tabs für das, was OP wollte nutzen können.