5

Quiero resaltar la página actual en el menú de navegación. Obviamente necesito darle al menú enlaces una clase como 'activa' cuando estás en su página. Este es un problema clásico y he visto muchas soluciones proposed. Mi problema es que los odio a todos y no considero que ninguno de ellos sea muy SECO. Por ejemplo:¿Por qué tengo que pasar RequestContext en todas mis respuestas?

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

La etiqueta lleva su solicitud actual y una expresión url y vuelve 'activo' si está actualmente en esta página. Alternativamente, esto se puede hacer con vistas nombradas en lugar de urls, pero el principio es el mismo.

Mi principal problema con esto es que mi navegación será llamado en el 99% de mis puntos de vista y, sin embargo, con el fin de obtener la variable solicitud actual todavía tengo analizar una RequestContext a la plantilla con algo como esto:

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

¿Por qué tengo que agregar esta línea de instancia de contexto a cada una de mis vistas cuando probablemente todas menos necesitan la variable de solicitud para obtener la url/vista actual para resaltar el enlace activo? Esto parece terriblemente húmedo, especialmente para una característica que debe estar en la gran mayoría de los sitios de django. Deseo que la solicitud se incluya por defecto y poder suprimirla opcionalmente. No puedo encontrar una forma de hacerlo en middleware ya que no puedo interceptar la plantilla antes de que se represente después de que la vista la haya devuelto.

¿Alguna sugerencia?

Respuesta

16

Su intención tiene sentido, necesitará RequestContext la mayor parte del tiempo y solo en raras ocasiones se puede omitir con seguridad por motivos de rendimiento. La solución es simple, en lugar de render_to_response uso direct_to_template atajo:

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 decorador de django-annoying:

from annoying.decorators import render_to 

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

¡El decorador @render_to es brillante! ¡Gracias! – Jimmy

+0

+1 por recomendar @render_to! tenga en cuenta que [django-fastidioso] (https://github.com/skorokithakis/django-annoying) ha sido tomado y movido debido a la inactividad – antiplex

+2

4 años después, y Django 1.5 ha eliminado el 'direct_to_template'. ¿Cuál sería ahora la forma recomendada para hacer esto, sin usar django-molesto – Patrick

1

No tiene por qué hacer nada con el marcado de su navegación para darle al estilo actual un estilo diferente: hay maneras declarativas de hacerlo con CSS.

Ver mi respuesta aquí: Django: Is there a better way to bold the current page link para un ejemplo.

+0

Nombrar sus páginas con identificaciones del cuerpo es una buena idea, pero la etiqueta del cuerpo, junto con la navegación, está en una plantilla base. Podría bloquearlo y agregar * {% block body_id%} my-page {% endblock%} * a cada plantilla extendida, pero de nuevo, ¿dónde está DRY? ¿Hay alguna forma de automatizar esto? Me gustaría utilizar la vista con nombre como la identificación del cuerpo o slugify o algo, en lugar de tener que nombrarla explícitamente y tener que mantener dos 'nombres' separados para cada vista: uno para la vista en sí y otro para el css id. – Jimmy

+0

Mi Django-fu está oxidado, pero en lugar de cambiar cada plantilla que se extiende, ¿podría pasar el nombre CSS de contacto() y familia: def contacto (solicitud): render_to_response ('contact.html', {'cssClass': ' página de contacto ',' myvar ': myvar}, ...)? Todavía no está perfectamente seco, pero no está mal. – RichieHindle

0

Para referencia futura, se puede utilizar django-tabs por hacer lo que quería OP.

Cuestiones relacionadas