Pergunta

Eu tenho um modelo base.html que contém uma lista de links.

Exemplo:

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

Então eu tenho na minha views.py uma definição para cada um dos index.html, stuff.html, about.html e contact.html. Cada um desses modelos simplesmente derivam de um modelo base.html e definir seus respectivos títulos e conteúdos.

A minha pergunta é sobre as coisas / acima Eu tenho um class = "atual".

Eu gostaria de fazer a página atual que eu estou em ter esse atributo de classe.

Eu poderia definir uma variável diferente em cada vista como current_page = "sobre" e depois fazer um comparar o modelo com {% ifequal %} em cada elemento de classe de cada link, mas que parece ser a duplicação de trabalho (por causa da variável vista adicional) .

Existe uma maneira melhor? Talvez se há uma maneira de obter o nome da função visão de que o modelo foi preenchido a partir automaticamente eu não teria necessidade de definir a variável extra? Também parece ser um monte de ifequals.

Foi útil?

Solução

Aqui está uma maneira elegante de fazer isso, que eu copiado de algum lugar e eu só desejo que eu poderia lembrar onde, para que eu pudesse dar-lhes o crédito. 8 -)

I atribuir um id para cada uma das minhas páginas (ou todas as páginas dentro de uma seção) como este:

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

E, em seguida, um id para os links correspondentes:

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

E a na CSS eu definir uma regra 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. */
}
.

Então, isso funciona em uma maneira na maior parte declarativa para controlar o estilo da ligação que a página atual pertence Você pode vê-lo em ação aqui: http://entrian.com/source-search/

É um sistema muito limpo e simples uma vez que você configurá-lo, porque:

  • Você não precisa mexer sobre com markup de modelo em suas ligações
  • Você não acabam usando grande declarações switch ou declarações if / else / else feio
  • Como adicionar páginas a uma seção simplesmente funciona [TM]
  • Mudar a forma como as coisas parecem sempre apenas significa mudar o CSS, não a marcação.

Eu não estou usando Django, mas este sistema funciona em qualquer lugar. No seu caso, onde "configurar seus respectivos títulos e conteúdo", você também precisa definir o body id, e não há nenhuma outra marcação Django necessário.

Esta ideia estende-se facilmente a outras situações, bem como, por exemplo. "Eu quero um link de download na barra lateral em todas as páginas, exceto as próprias páginas de download." Você pode fazer isso em CSS como este:

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

em vez de ter de colocar markup de modelo condicional no HTML da barra lateral.

Outras dicas

Não usou Django, mas eu lidei com o mesmo problema em Kohana (PHP) e Rails .

O que fazer em 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>

O que fazer em 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>

Eu vejo apenas um par de maneiras de fazer isso, evitando ifequals repetidas:

  1. Javascript. Algo ao longo das linhas de (jQuery):

    var parts = window.location.pathname.split('/');
    var page = parts[parts.length-1];
    $('#sidebar1 a[href*=' + page + ']').addClass('current');
    
  2. Alterar as suas opiniões para conter uma lista de páginas com seus títulos e URLs associadas e criar uma {% for%} loop no seu modelo, que vai passar por essa lista, e adicionar uma única {% ifequal%} .

Opção 2 ser o favorito de onde eu estou. Se a lógica para todas as suas páginas é a mesma, e apenas os modelos diferem, você pode considerar o uso do modelo flatpages para cada uma de suas páginas. Se a lógica é diferente, e você precisa de modelos diferentes, que você pode considerar o uso de um aplicativo menuing de algum tipo. Um plug descarado: Eu tenho um menuing aplicativo da minha própria

Se você adicionar o processador de contexto request, é bastante simples:

settings.py:

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

Agora você tem acesso ao HttpRequest, que contém o caminho pedido. Destacando a página atual é uma simples questão de verificar se o caminho corresponde o destino do link, ou seja, você já está lá:

<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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top