2
respostas

Como ativar os links do menu automaticamente

Eu acho bem interessante a possibilidade de exibir no menu o link ativo, relativo à página que está sendo acessada, pois mostra de uma forma visual bem rápida onde o usuário está.

Como estamos usando um partial para o header do site e ele é incorporado em cada uma das páginas, isso precisa ser feito de forma dinâmica. Após algumas tentativas sem sucesso, fiz umas pesquisas e encontrei esse post, que de forma bem simples explica como fazer.

Basicamente precisa verificar se nas configurações do projeto, no nosso caso deste curso no arquivo settings da pasta alura_receita (se você seguiu conforme o professor fez nas aulas), verifique se está com a opção django.template.context_processors.request dentro de TEMPLATES > OPTIONS > context_processors. Tendo essa configuração, basta acessar a partial com o header e incluir uma atribuição de variável para cada url, para poder verificá-la na hora de definir a classe "active", por exemplo.

Segue abaixo o código que eu usei no meu caso de forma resumida, já implementando também no menu o link de admin quando é um superuser:

{% load static %}
{% url 'index' as url_inicio %}
{% url 'dashboard' as url_dashboard %}
{% url 'cria_receita' as url_cria_receita %}
{% url 'login' as url_login %}
{% url 'cadastro' as url_cadastro %}
...
<!-- Nav Start -->
  <div class="classynav">
    <ul>
      {% if user.is_authenticated %}
      <li class="nav-item {% if request.path == url_inicio %}active{% endif %}">
        <a href="{% url 'index' %}">Início</a>
      </li>
      <li class="nav-item {% if request.path == url_dashboard %}active{% endif %}">
        <a href="{% url 'dashboard' %}">Minhas receitas</a>
      </li>
      <li class="nav-item {% if request.path == url_cria_receita %}active{% endif %}">
        <a href="{% url 'cria_receita' %}">Criar receita</a>
      </li>
      {% if user.is_superuser %}
      <li>
        <a href="{% url 'admin:index' %}" target="_blank">Admin</a>
      </li>
      {% endif %}
      <li>
        <a href="{% url 'logout' %}">Logout</a>
      </li>
       {% else %}
       <li class="nav-item {% if request.path == url_cadastro %}active{% endif %}">
         <a href="{% url 'cadastro' %}">Cadastro</a>
        </li>
        <li class="nav-item {% if request.path == url_login %}active{% endif %}">
          <a href="{% url 'login' %}">Login</a>
         </li>
         {% endif %}
       </ul>
    <!-- Newsletter Form -->
       <div class="search-btn">
         <i class="fa fa-search" aria-hidden="true"></i>
       </div>
  </div>
  <!-- Nav End -->
...

Fazendo desta forma, quando eu acesso a página inicial, o link referente a ela fica verde (do mesmo jeito que fica quando passa o mouse por cima).

2 respostas

Oii Jean, como você está?

Sensacional! Obrigada por compartilhar a respeito disso conosco e detalhar tão bem como fez cada procedimento. Com certeza irá ajudar outros alunos.

Qualquer dúvida estou por aqui.

Grande abraço!

Olá Nádia, bom dia! Estou bem obrigado e você?

Foi um prazer poder agregar de alguma forma! Inclusive eu descobri uma forma melhor de fazer isso, para não ter tantos if's dentro do template do header, que é usando templatetags customizadas. Assim poderia usar somente uma tag, passar os parâmetros e deixar a lógica para dentro do método.

Para fazer isso basta dentro do app relacionado à templatetag que for criar, adicionar a pasta templatetags, com o arquivo de inicialização de módulo (__init__.py) e o arquivo onde vai incluir as tags customizadas (considerando que cada tag será pequena e não ficará muito bagunçado deixar tudo em um arquivo só). No meu caso criei o arquivo helpers.py.

Nesse arquivo eu importei a Library do django templates, para poder registrar minha tag corretamente e ela poder ser reconhecida pelo template, dessa forma: from django.template import Library e logo em seguida instanciei o register, register = Library().

Essa instância agora pode ser usada como um decorator, que recebe como parâmetro a função que vai logo abaixo e a usa para passar o que precisa ser feito para o template, dessa forma:

@register.simple_tag
def link_eh_ativo(request, url):
    return 'active' if request.path == url else ''

Feito isso, adicione o import da templatetag criada no __init__.py. No meu caso o import ficou assim from .helpers import link_eh_ativo.

No template onde estava antes usando o if para verificar o request.path, agora basta carregar suas templatetags, incluindo no início do arquivo {% load helpers %} (no meu caso foi assim, por causa do nome do arquivo) e, no lugar do if passar a tag customizada, ou seja, o que antes estava assim:

<li class="nav-item {% if request.path == url_inicio %}active{% endif %}">
    <a href="{% url 'index' %}">Início</a>
</li>

Passa a ficar assim:

<li class="nav-item {% link_eh_ativo request url_inicio %}">
    <a href="{% url 'index' %}">Início</a>
</li>

Dessa forma o template fica mais limpo e com menos repetição de código, podendo reaproveitar o método em outros templates e, caso a lógica dele mude por algum motivo, precisará trocar em apenas um lugar.

Espero que isso possa ajudar alguém de alguma forma, grande abraço!