Acabei de fazer meu primeiro pequeno webapp em Django e adorei. Estou prestes a começar a converter um antigo site PHP de produção em django e, como parte de seu modelo, há uma barra de navegação.
Em PHP, eu verifico o URL de cada opção de navegação em relação ao URL atual, no código do modelo e aplico uma classe CSS se eles estiverem alinhados. É terrivelmente confuso.
Existe algo melhor para django ou uma boa maneira de lidar com o código no modelo?
Para começar, como faria para obter o URL atual?
django
navigation
Oli
fonte
fonte
<a href="{% url "view:name" %}" {% active_class "view:name" %}>
. Você pode opcionalmente usá-lo para gerar apenas o" active"
valor (passandoFalse
como um segundo argumento para a tag) para anexar a um atributo de classe existente, mas para a maioria dos links de navegação, esse exemplo é o que eu uso.Respostas:
Eu uso a herança do modelo para personalizar a navegação. Por exemplo:
base.html
about.html
fonte
<ul id="nav">....</ul>
para um arquivo diferente, digamos tabs.html. Portanto, agora base.html contido{%block nav%}{%include "tabs.html"%}{%endblock%}
e, em seguida, o destaque da guia ativa parou de funcionar (em about.html acima). Estou perdendo alguma coisa?include
tag funciona. Verifique a nota incluída nos documentos: docs.djangoproject.com/en/dev/ref/templates/builtins/#include No seu caso, no momento em que você está tentando substituir o modelo base emabout.html
, acho que você já tem um bloco HTML renderizado, ao invés de um bloco de template Django esperando para ser processado.Você não precisa de um if para fazer isso, dê uma olhada no seguinte código:
tags.py
urls.py
base.html
é isso aí. para detalhes de implementação, dê uma olhada em:
gnuvince.wordpress.com
110j.wordpress.com
fonte
django.core.context_processors.request
ao seuTEMPLATE_CONTEXT_PROCESSORS
insettings.py
mysite.com
(como home) emysite.com/blog
, pois o caminho será mostrado como/
e/blog/
(respectivamente), resultando em uma correspondência para o anterior a cada vez. Se você não usar/
como um patamar, pode estar tudo bem, caso contrário, eu apenas usoreturn 'active' if pattern == request.path else ''
(ainda não vi problemas com isso, mas acabei de configurar usando isso).Gostei da limpeza do 110j acima, então peguei a maior parte dele e refatorei para resolver os 3 problemas que tive com ele:
Aqui está:
tags.py:
urls.py:
base.html:
fonte
Eu sou o autor de django-lineage que escrevi especificamente para resolver esta questão: D
Fiquei aborrecido ao usar o método jpwatts (perfeitamente aceitável) em meus próprios projetos e me inspirei na resposta do 110j. A linhagem se parece com isto:
ancestor
é simplesmente substituído por "ativo" se o argumento corresponder ao início do URL da página atual.Argumentos variáveis e
{% url %}
resolução reversa de tipo completo também são suportados. Eu polvilhei algumas opções de configuração, desenvolvi um pouco e empacotei para que todos possam usar.Se alguém estiver interessado, leia um pouco mais sobre isso em:
>> github.com/marcuswhybrow/django-lineage
fonte
Desde Django 1.5 :
Portanto, se você estiver usando essas visualizações, poderá adicionar algo
breadcrumbs
como um campo de nível de classe e usá-lo em seus modelos.Exemplo de código de visualização:
Em seu modelo, você pode usá-lo desta forma:
Se você deseja "destacar" itens de navegação pai adicionalmente, é necessário estender a
breadcrumbs
lista:... e em seu modelo:
Esta é uma solução fácil e limpa e funciona muito bem com navegação aninhada.
fonte
.active
?breadcrumbs
se quiser. Mas você tem razão - meu exemplo não é o melhor.Você pode aplicar uma classe ou id ao elemento do corpo da página, em vez de a um item de navegação específico.
HTML:
CSS:
fonte
Eu faço assim:
e então tudo que tenho a fazer é, na minha opinião, adicionar
{'active_tab': 'statistics'}
ao meu dicionário de contexto.Se estiver usando,
RequestContext
você pode obter o caminho atual em seu modelo como:E na sua opinião:
fonte
Peguei o código do nivhab acima e removi algumas estranhezas e o transformei em um templatetag limpo, modifiquei para que / account / edit / ainda torne / account / tab ativo.
fonte
Esta é apenas uma variante da solução css proposta por Toba acima:
Inclua o seguinte em seu modelo básico:
Então, em seus modelos que estendem o uso básico:
Você pode então usar css para destacar a área atual com base na tag do corpo (por exemplo, se tivermos um link com um id de nav-home):
fonte
Você pode usar a função reversa com os parâmetros apropriados para obter o url atual.
fonte
Obrigado por suas respostas até agora, senhores. Eu optei por algo um pouco diferente novamente ..
No meu modelo:
Depois de descobrir em qual página estou na lógica (geralmente em urls.py), passo
class="selected"
como parte do contexto sob o nome correto para o modelo.Por exemplo, se eu estiver na página link1, vou anexar
{'link1_active':' class="selected"'}
ao contexto do modelo para coletar e injetar.Parece funcionar e está bastante limpo.
Editar: para manter o HTML fora do meu controlador / visualização, modifiquei um pouco:
Isso torna o modelo um pouco menos legível, mas concordo, é melhor não empurrar HTML bruto do arquivo de urls.
fonte
Tenho vários menus na mesma página que são criados dinamicamente por meio de um loop. As postagens acima relacionadas ao contexto me deram uma solução rápida. Espero que isso ajude alguém. (Eu uso isso além da tag de modelo ativa - minha correção resolve o problema dinâmico). Parece uma comparação boba, mas funciona. Eu escolhi nomear as variáveis active_something-unique e something-unique, dessa forma funciona com menus aninhados.
Aqui está uma parte da visualização (o suficiente para entender o que estou fazendo):
E isso é do modelo:
fonte
Minha solução foi escrever um processador de contexto simples para definir uma variável com base no caminho da solicitação:
(Não se esqueça de adicionar seu processador personalizado a TEMPLATE_CONTEXT_PROCESSORS em settings.py.)
Então, no modelo básico, uso uma tag ifequal por link para determinar se devo acrescentar a classe "ativa". Concedido, essa abordagem é estritamente limitada à flexibilidade de sua estrutura de caminho, mas funciona para minha implantação relativamente modesta.
fonte
Eu só queria compartilhar minha pequena melhoria na postagem de nivhab. Em meu aplicativo, tenho subnavigações e não queria ocultá-las usando apenas CSS, portanto, precisava de algum tipo de tag "if" para exibir ou não a subnavegação de um item.
Você pode usar isso basicamente da mesma forma que a tag ativa:
fonte
Apenas mais um aprimoramento da solução original.
Isso aceita vários padrões, e o que é melhor também é padrões sem nome escritos como URL relativo envolvido em '"', como a seguir:
Tag funciona assim:
fonte
Usei jquery para destacar minhas barras de navegação. Esta solução simplesmente adiciona a classe css "ativa" ao item que se ajusta ao seletor css.
fonte
Uma pequena melhoria em relação à resposta de @tback , sem quaisquer
%if%
tags:Use-o em seu modelo assim:
E inclua
"django.core.context_processors.request"
em suaTEMPLATE_CONTEXT_PROCESSORS
configuração.fonte
Achei que o melhor é usar uma tag de inclusão:
templates/fnf/nav_item.html
Este é apenas o meu item de navegação básico de boot que desejo renderizar.
Ele obtém o valor href e, opcionalmente, o valor link_name.
is_active
é calculado com base na solicitação atual.templatetags/nav.py
Em seguida, use-o em um nav:
templates/fnf/nav.html
fonte
/about/company-history/
ou/about/what-we-do/
is_active
podem ser substituídas e outras chaves adicionadas ao dicionário retornadas. Além disso, o cheque pode sercontext.request.resolver_match.url_name.startswith(x)
ou qualquer outra coisa. Além disso, você pode ter código antes da instrução return para estabelecer os valores de dict. Além disso, você pode usar modelos diferentes, ou seja, um paratop_level_nav.html
com lógica diferente, etc.Modificando ligeiramente a resposta de Andreas, parece que você pode passar o nome da rota de urls.py para a tag do modelo. No meu exemplo
my_tasks
, e na função de tag de modelo, use a função reversa para descobrir qual deve ser a URL, então você pode compará-la com a URL no objeto de solicitação (disponível no contexto do modelo)urls.py
template.html
fonte
Eu sei que estou atrasado para a festa. Não gostei de nenhuma das soluções populares:
O método de bloqueio parece errado: acho que a navegação deve ser independente.
O método template_tag parece errado: eu não gosto de ter que obter o url da url-tag primeiro. Além disso, acho que a classe css deve ser definida no modelo, não na tag.
Portanto, escrevi um filtro que não tem as desvantagens que descrevi acima. Ele retorna
True
se um url está ativo e, portanto, pode ser usado com{% if %}
:O código:
Apenas certifique-se de usar
RequestContext
em páginas com navegação ou de habilitar a solicitação context_processor em seusettings.py
fonte
Eu vi jpwatts ' 110.º-J ' s, nivhab 's & Marcus Whybrow ' s respostas, mas todos eles parecem falta em alguma coisa: o que acontece com o caminho da raiz? Por que está sempre ativo?
Então criei uma outra forma, mais fácil, que faz o "controlador" decidir por si mesmo e acho que resolve a maioria dos grandes problemas.
Aqui está minha tag personalizada:
Então, o "controlador" declara as classes CSS necessárias (na verdade, o mais importante é que declara sua presença ao template)
E, finalmente, eu o renderizo na minha barra de navegação:
Portanto, cada página tem seu próprio
nav_css_class
valor a ser definido e, se for definido, o modelo torna-se ativo: sem necessidade derequest
no contexto do modelo, sem pareamento de URL e sem mais problemas com páginas multi-URL ou página raiz.fonte
Inspirado por esta solução , comecei a usar esta abordagem:
fonte
Aqui está minha chance. Acabei implementando uma classe em minhas visualizações que contém minha estrutura de navegação (plana com alguns metadados). Em seguida, injeto isso no modelo e o renderizo.
Minha solução lida com i18n. Provavelmente deveria ser abstraído um pouco mais, mas eu realmente não me preocupei com isso.
views.py:
Eu defini a lógica do template usando inclui como este. Modelo base:
Inclusão real (inclui / navegação.html):
Esperançosamente, alguém achará isso útil! Acho que seria muito fácil estender essa ideia para oferecer suporte a hierarquias aninhadas, etc.
fonte
Crie um modelo de inclusão "intranet / nav_item.html":
E inclua-o no elemento nav:
E você precisa adicionar isso às configurações:
fonte
aqui está uma solução bastante simples, https://github.com/hellysmile/django-activeurl
fonte
desta pergunta SO
Repita conforme necessário para cada link.
fonte
/blog/posts/2021/04/12
fosse o url, o item / blog / nav estaria ativo.Questions
,Tags
,Users
,Badges
,Unanswered
,Ask Question
. não funcionará paraQuestions
, mas para todos os outros navs funcionará bem.Eu também usei o jQuery para destacá-lo e considerá-lo mais elegante do que bagunçar o template com tags de template Django não-semânticas.
O código abaixo funciona com menus suspensos aninhados no bootstrap 3 (destaca o elemento pai e o
<li>
elemento filho .Também é muito fácil adicionar um
click
eventoreturn false
(ou alterar ohref
atributo para#
) para a página atual, sem alterar a marcação de template / html:fonte
Eu uso uma combinação deste mixin para visualizações baseadas em classe:
com isso no modelo:
fonte
O meu é um pouco semelhante a outra abordagem JS enviada anteriormente .. só sem jQuery ...
Digamos que temos em base.html o seguinte:
Acabei de fazer minha hierarquia para seguir um determinado padrão de URL ... após o endereço do host ... eu tenho minha categoria principal, por exemplo, casa, notícias, análise, etc. e a regex apenas puxa a primeira palavra do local
fonte