5

Desidero evidenziare la pagina corrente nel menu di navigazione. Ovviamente ho bisogno di dare ai collegamenti del menu una classe come "attiva" quando sei sulla loro pagina. Questo è un problema classico e ho visto molte soluzioni proposed. Il mio problema è che odio tutti loro e ritengo che nessuno di loro sia molto ASCIUTTO. Per esempio:Perché mai devo passare a RequestContext in tutte le mie risposte?

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

Il tag prende la vostra richiesta corrente e un'espressione URL e restituisce 'attivo', se siete attualmente in questa pagina. In alternativa, questo può essere fatto con viste nominate piuttosto che url ma il principio è lo stesso.

Il mio problema principale di questo è che la mia navigazione sarà chiamato sul 99% delle mie opinioni e tuttavia, al fine di ottenere la variabile richiesta corrente Ho ancora analizzare una RequestContext al modello con qualcosa di simile:

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

Perché devo aggiungere questa linea di istanza di contesto a ciascuna delle mie visualizzazioni quando probabilmente uno solo di essi ha bisogno della variabile di richiesta per ottenere l'URL/vista corrente per evidenziare il collegamento attivo? Questo sembra terribilmente umido, specialmente per una funzionalità che deve essere nella grande maggioranza dei siti di Django. Voglio che la richiesta sia inclusa di default ed essere in grado di sopprimerla opzionalmente. Non riesco a trovare un modo per farlo nel middleware poiché non riesco a intercettare il modello prima del suo rendering dopo che la vista lo ha restituito.

Qualche suggerimento?

risposta

16

L'intenzione è ragionevole, è necessario il RequestContext la maggior parte del tempo e solo raramente può essere omesso in sicurezza per motivi di prestazioni. La soluzione è semplice, invece di render_to_response uso direct_to_template scorciatoia:

from django.views.generic.simple import direct_to_template 

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

... o render_to decoratore da django-annoying:

from annoying.decorators import render_to 

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

Il decoratore @render_to è geniale! Grazie! – Jimmy

+0

+1 per aver raccomandato @render_to! nota che [django-fastidioso] (https://github.com/skorokithakis/django-annoying) è stato preso in carico e spostato a causa dell'inattività – antiplex

+2

4 anni dopo e Django 1.5 ha rimosso il 'direct_to_template'. Quale sarebbe ora il modo consigliato per farlo, senza usare django-fastidioso – Patrick

1

Non devi necessariamente fare nulla per il markup della tua navigazione per dare a quello attuale uno stile diverso - ci sono modi dichiarativi per farlo usando il CSS.

Vedere la mia risposta qui: Django: Is there a better way to bold the current page link per un esempio.

+0

Il nome delle pagine con l'id del corpo è una buona idea, ma il tag del corpo, insieme alla navigazione, si trova in un modello di base. Potrei bloccarlo e aggiungere * {% block body_id%} my-page {% endblock%} * a ogni modello di estensione ma ancora, dov'è il DRY? C'è un modo per automatizzare questo? Vorrei usare la vista denominata come id del body o slugify o qualcosa, piuttosto che doverlo esplicitamente nominare e mantenere due "nomi" separati per ogni vista: uno per la vista stessa e uno per la ID css. – Jimmy

+0

Il mio Django-fu è arrugginito, ma piuttosto che modificare ogni modello di estensione, potresti passare il nome CSS da contact() e family: def contact (request): render_to_response ('contact.html', {'cssClass': ' contact-page ',' myvar ': myvar}, ...)? Ancora non perfettamente SECCO, ma non male. – RichieHindle

0

Per riferimento futuro, si può usare django-tabs per fare quello che voleva OP.

Problemi correlati