Pregunta

Tengo una plantilla base.html que contiene una lista de enlaces.

Ejemplo:

   <div id="sidebar1">
        <ul>
        <li><a href="/" title="">Index</a></li>
        <li><a href="/stuff/" title="" class="current">Stuff</a></li>
        <li><a href="/about/" title="">About Me</a></li>
        <li><a href="/contact/" title="">Contact Me</a></li>
    </div>

Luego tengo en mi views.py una definición para cada uno de index.html, stuff.html, about.html y contact.html. Cada una de esas plantillas simplemente deriva de una plantilla base.html y establece sus propios títulos y contenidos respectivos.

Mi pregunta es sobre lo anterior / cosas que tengo una clase = " actual " ;.

Me gustaría hacer que la página actual en la que estoy tenga ese atributo de clase.

Podría establecer una variable diferente en cada vista como current_page = " about " y luego haga una comparación en la plantilla con {% ifequal%} en cada elemento de clase de cada enlace, pero eso parece duplicar el trabajo (debido a la variable de vista adicional).

¿Hay una mejor manera? ¿Tal vez si hay una manera de obtener el nombre de la función de vista desde el que se rellenó la plantilla automáticamente, no necesitaría establecer la variable adicional? También parece un montón de ifequals.

¿Fue útil?

Solución

Aquí hay una manera elegante de hacer esto, que copié de alguna parte y solo desearía poder recordar dónde, para poder darles el crédito. 8-)

Asigno un id a cada una de mis páginas (o todas las páginas dentro de una sección) como esta:

In index.html:    <body id='section-intro'>...
In faq.html:      <body id='section-faq'>...
In download.html: <body id='section-download'>...

Y luego un id para los enlaces correspondientes:

<li id='nav-intro'><a href="./">Introduction</a></li>
<li id='nav-faq'><a href="./faq.html">FAQ</a></li>
<li id='nav-download'><a href="./download.html">Download</a></li>

Y en el CSS establecí una regla como esta:

#section-intro #nav-intro,
#section-faq #nav-faq,
#section-download #nav-download {
    font-weight: bold;
    /* And whatever other styles the current link should have. */
}

Entonces, esto funciona de una manera principalmente declarativa para controlar el estilo del enlace al que pertenece la página actual. Puede verlo en acción aquí: http://entrian.com/source-search/

Es un sistema muy limpio y simple una vez que lo ha configurado, porque:

  • No necesita meterse con el marcado de plantillas en sus enlaces
  • No terminas usando grandes y feas declaraciones de switch o if / else / else declaraciones
  • Agregar páginas a una sección Just Works [TM]
  • Cambiar la apariencia de las cosas solo significa cambiar el CSS, no el marcado.

No estoy usando Django, pero este sistema funciona en cualquier lugar. En su caso, donde '' establezca sus propios títulos y contenidos respectivos '' también necesita establecer el body id , y no se requiere otro marcado de Django.

Esta idea se extiende fácilmente a otras situaciones también, por ejemplo. "Quiero un enlace de descarga en la barra lateral de cada página, excepto en las páginas de descarga". Puede hacerlo en CSS de esta manera:

#section-download #sidebar #download-link {
    display: none;
}

en lugar de tener que poner un marcado de plantilla condicional en el HTML de la barra lateral.

Otros consejos

No he usado Django, pero he tratado el mismo problema en Kohana (PHP) y Rails .

Lo que hago en Kohana:

<li><a href="/admin/dashboard" <?= (get_class($this) == 'Dashboard_Controller') ? "class=\"active\"" : NULL ?>>Dashboard</a></li>
<li><a href="/admin/campaigns" <?= (get_class($this) == 'Campaigns_Controller') ? "class=\"active\"" : NULL ?>>Campaigns</a></li>
<li><a href="/admin/lists" <?= (get_class($this) == 'Lists_Controller') ? "class=\"active\"" : NULL ?>>Lists</a></li>

Lo que hago en Rails:

<li><a href="/main" <%= 'class="active"' if (controller.controller_name == 'main') %>>Overview</a></li>
<li><a href="/notifications" <%= 'class="active"' if (controller.controller_name == 'notifications') %>>Notifications</a></li>
<li><a href="/reports" <%= 'class="active"' if (controller.controller_name == 'reports') %>>Reports</a></li>

Solo veo un par de formas de hacerlo, mientras evito ifequals repetidos:

  1. Javascript. Algo en la línea de (jQuery):

    var parts = window.location.pathname.split('/');
    var page = parts[parts.length-1];
    $('#sidebar1 a[href*=' + page + ']').addClass('current');
    
  2. Cambie sus vistas para que contengan una lista de páginas con sus títulos y URL asociados y cree un bucle {% for%} en su plantilla, que pasará por esa lista y agregará un solo {% ifequal%} .

La opción 2 es la favorita desde mi punto de vista. Si la lógica de todas sus páginas es la misma, y ??solo las plantillas difieren, puede considerar usar el modelo FlatPages para cada una de sus páginas. Si la lógica es diferente y necesita diferentes modelos, puede considerar usar una aplicación de menús de algún tipo. Un complemento descarado: tengo una aplicación de menús propia

Si agrega el procesador de contexto request , es bastante sencillo:

settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth'  # admin app wants this too
)

Ahora tiene acceso a HttpRequest , que contiene la ruta de solicitud. Destacar la página actual es una simple cuestión de verificar si la ruta coincide con el destino del enlace, es decir, ya está allí:

<li><a class="{% if request.path == '/' %}current{% endif %}" href="/">Index</a></li>
<li><a class="{% if request.path == '/stuff/' %}current{% endif %}" href="/stuff/">Stuff</a></li>
<li><a class="{% if request.path == '/about/' %}current{% endif %}" href="/about/">About Me</a></li>
<li><a class="{% if request.path == '/contact/' %}current{% endif %}" href="/contact/">Contact Me</a></li>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top