Acabo de hacer mi primera pequeña aplicación web en django y me encanta. Estoy a punto de comenzar a convertir un antiguo sitio PHP de producción en django y, como parte de su plantilla, hay una barra de navegación.
En PHP, verifico la URL de cada opción de navegación con la URL actual, en el código de la plantilla y aplico una clase CSS si se alinean. Es terriblemente desordenado.
¿Hay algo mejor para django o una buena forma de manejar el código en la plantilla?
Para empezar, ¿cómo puedo conseguir la URL actual?
django
navigation
Oli
fuente
fuente
<a href="{% url "view:name" %}" {% active_class "view:name" %}>
. Opcionalmente, puede usarlo para generar solo el" active"
valor (pasandoFalse
como un segundo argumento a la etiqueta) para agregarlo a un atributo de clase existente, pero para la mayoría de los enlaces de navegación, ese ejemplo es el que uso.Respuestas:
Utilizo la herencia de plantillas para personalizar la navegación. Por ejemplo:
base.html
about.html
fuente
<ul id="nav">....</ul>
archivo a un archivo diferente, digamos tabs.html. Así que ahora base.html contenido{%block nav%}{%include "tabs.html"%}{%endblock%}
y luego resaltado de la pestaña activa dejó de funcionar (en about.html arriba). ¿Me estoy perdiendo algo?include
etiqueta. Consulte la nota incluida en los documentos: docs.djangoproject.com/en/dev/ref/templates/builtins/#include En su caso, para cuando intente anular la plantilla base enabout.html
, creo que ya ha ya tiene un bloque HTML renderizado, en lugar de un bloque de plantilla de Django esperando ser procesado.No necesita un si para hacer eso, eche un vistazo al siguiente código:
tags.py
urls.py
base.html
Eso es. para obtener detalles sobre la implementación, consulte:
gnuvince.wordpress.com
110j.wordpress.com
fuente
django.core.context_processors.request
a tuTEMPLATE_CONTEXT_PROCESSORS
insettings.py
mysite.com
(Como inicio) ymysite.com/blog
, ya que la ruta se mostrará como/
y/blog/
(respectivamente) dando una coincidencia para el primero cada vez. Si no lo usa/
como aterrizaje, puede estar bien, de lo contrario, solo lo usoreturn 'active' if pattern == request.path else ''
(todavía no he visto problemas con esto, pero solo configuré el uso de esto).Me gustó la limpieza de 110j anterior, así que tomé la mayor parte y lo refactoricé para resolver los 3 problemas que tuve con él:
Aquí está:
tags.py:
urls.py:
base.html:
fuente
Soy el autor de django-lineage que escribí específicamente para resolver esta pregunta: D
Me molestó usar el método jpwatts (perfectamente aceptable) en mis propios proyectos y me inspiré en la respuesta de 110j. El linaje se ve así:
ancestor
simplemente se reemplaza por "activo" si el argumento coincide con el inicio de la URL de la página actual.{% url %}
También se admiten argumentos variables y resolución inversa de tipo completo . Agregué algunas opciones de configuración, lo desarrollé un poco y lo empaqueté para que todos lo usaran.Si alguien está interesado, lea un poco más sobre esto en:
>> github.com/marcuswhybrow/django-lineage
fuente
Desde Django 1.5 :
Entonces, si está usando tales vistas, puede agregar algo
breadcrumbs
como un campo de nivel de clase y usarlo en sus plantillas.Ejemplo de código de vista:
En su plantilla, puede usarlo de esta manera:
Si desea "resaltar" adicionalmente los elementos de navegación principales, debe ampliar la
breadcrumbs
lista:... y en tu plantilla:
Esta es una solución fácil y limpia y funciona bastante bien con la navegación anidada.
fuente
.active
?breadcrumbs
si lo desea. Pero tienes razón: mi ejemplo no es el mejor.Puede aplicar una clase o identificación al elemento del cuerpo de la página, en lugar de a un elemento de navegación específico.
HTML:
CSS:
fuente
Lo hago así:
y luego todo lo que tengo que hacer es agregar
{'active_tab': 'statistics'}
a mi diccionario de contexto.Si está utilizando
RequestContext
, puede obtener la ruta actual en su plantilla como:Y en tu opinión:
fuente
Tomé el código de nivhab anterior y eliminé algunas rarezas y lo convertí en una etiqueta de plantilla limpia, la modifiqué para que / account / edit / aún active / account / tab.
fuente
Esta es solo una variante de la solución css propuesta por Toba anteriormente:
Incluya lo siguiente en su plantilla base:
Luego, en tus plantillas que extienden el uso base:
Luego puede usar css para resaltar el área actual según la etiqueta del cuerpo (por ejemplo, si tenemos un enlace con una identificación de nav-home):
fuente
Puede utilizar la función inversa con los parámetros adecuados para obtener la URL actual.
fuente
Gracias por sus respuestas hasta ahora, caballeros. He optado por algo ligeramente diferente de nuevo ...
En mi plantilla:
Una vez que he descubierto en qué página estoy en la lógica (generalmente en urls.py), paso
class="selected"
como parte del contexto bajo el nombre correcto a la plantilla.Por ejemplo, si estoy en la página link1, agregaré
{'link1_active':' class="selected"'}
el contexto para que la plantilla se recupere e inyecte.Parece funcionar y está bastante limpio.
Editar: para mantener HTML fuera de mi controlador / vista, modifiqué esto un poco:
Hace que la plantilla sea un poco menos legible, pero estoy de acuerdo, es mejor no presionar HTML sin procesar desde el archivo de URL.
fuente
Tengo varios menús en la misma página que se crean dinámicamente a través de un bucle. Las publicaciones anteriores relacionadas con el contexto me dieron una solución rápida. Espero que esto ayude a alguien. (Utilizo esto además de la etiqueta de plantilla activa; mi solución resuelve el problema dinámico). Parece una comparación tonta, pero funciona. Elegí nombrar las variables active_something-unique y something-unique, de esta manera funciona con menús anidados.
Aquí hay una parte de la vista (suficiente para entender lo que estoy haciendo):
Y esto es de la plantilla:
fuente
Mi solución fue escribir un procesador de contexto simple para establecer una variable basada en la ruta de solicitud:
(No olvide agregar su procesador personalizado a TEMPLATE_CONTEXT_PROCESSORS en settings.py).
Luego, en la plantilla base, uso una etiqueta ifequal por enlace para determinar si agregar la clase "activa". De acuerdo, este enfoque está estrictamente limitado a la flexibilidad de la estructura de su ruta, pero funciona para mi implementación relativamente modesta.
fuente
Solo quería compartir mi pequeña mejora en la publicación de nivhab. En mi aplicación tengo subnavegaciones y no quería ocultarlas usando solo CSS, así que necesitaba algún tipo de etiqueta "if" para mostrar la subnavegación de un elemento o no.
Puede usar esto básicamente de la misma manera que la etiqueta activa:
fuente
Solo otra mejora de la solución original.
Esto acepta múltiples patrones y lo mejor es también patrones sin nombre escritos como URL relativa envuelta en '"', como sigue:
La etiqueta dice así:
fuente
Usé jquery para resaltar mis barras de navegación. Esta solución simplemente agrega la clase css "activa" al elemento que se ajusta al selector css.
fuente
Una pequeña mejora sobre la respuesta de @tback , sin
%if%
etiquetas:Úselo en su plantilla así:
E incluir
"django.core.context_processors.request"
en suTEMPLATE_CONTEXT_PROCESSORS
entorno.fuente
Encontré que lo mejor es usar una etiqueta de inclusión:
templates/fnf/nav_item.html
Este es solo mi elemento básico de navegación bootstrap que deseo representar.
Obtiene el valor href y, opcionalmente, el valor link_name.
is_active
se calcula en función de la solicitud actual.templatetags/nav.py
Luego úsalo en un navegador:
templates/fnf/nav.html
fuente
/about/company-history/
o/about/what-we-do/
is_active
se pueden reemplazar y se pueden devolver otras claves agregadas al diccionario. Además, el cheque puede sercontext.request.resolver_match.url_name.startswith(x)
o cualquier otra cosa. Además, puede tener código antes de la declaración de retorno para establecer los valores de dict. Además, puede usar diferentes plantillas, es decir, unatop_level_nav.html
con lógica diferente, etc.Modificando ligeramente la respuesta de Andreas, parece que puede pasar el nombre de la ruta desde urls.py a la etiqueta de la plantilla. En mi ejemplo
my_tasks
, y luego, en la función de etiqueta de plantilla, use la función inversa para averiguar cuál debería ser la URL, luego puede compararla con la URL en el objeto de solicitud (disponible en el contexto de la plantilla)urls.py
template.html
fuente
Sé que llego tarde a la fiesta. Sin embargo, no me gustó ninguna de las soluciones populares:
El método de bloqueo parece incorrecto: creo que la navegación debería ser autónoma.
El método template_tag parece incorrecto: no me gusta que primero tenga que obtener la URL de la etiqueta url. Además, creo que la clase css debería definirse en la plantilla, no en la etiqueta.
Por lo tanto, escribí un filtro que no tiene los inconvenientes que describí anteriormente. Devuelve
True
si una URL está activa y, por lo tanto, se puede usar con{% if %}
:El código:
Solo asegúrese de usar
RequestContext
en páginas con navegación o de habilitar la solicitud context_processor en susettings.py
fuente
He visto las respuestas de jpwatts ', 110j 's, nivhab ' s y Marcus Whybrow , pero todas parecen carecer de algo: ¿qué pasa con la ruta raíz? ¿Por qué siempre está activo?
Así que hice otra manera, más fácil, que hace que el "controlador" decida por sí mismo y creo que resuelve la mayoría de los grandes problemas.
Aquí está mi etiqueta personalizada:
Luego, el "controlador" declara las clases CSS necesarias (de hecho, lo más importante es que declara su presencia en la plantilla)
Y finalmente, lo renderizo en mi barra de navegación:
Entonces, cada página tiene su propio
nav_css_class
valor para configurar, y si está configurado, la plantilla se vuelve activa: no es necesariorequest
en el contexto de la plantilla, no hay parcelación de URL y no más problemas con las páginas de múltiples URL o la página raíz.fuente
Inspirado por esta solución , comencé a usar este enfoque:
fuente
Aquí está mi camino. Terminé implementando una clase en mis vistas que contiene mi estructura de navegación (plana con algunos metadatos). Luego inyecto esto en la plantilla y lo renderizo.
Mi solución trata con i18n. Probablemente debería resumirse un poco más, pero realmente no me he molestado con eso.
views.py:
Definí la lógica de la plantilla usando incluye como este. Plantilla base:
Incluido real (incluye / navigation.html):
¡Ojalá alguien lo encuentre útil! Supongo que sería bastante fácil extender esa idea para admitir jerarquías anidadas, etc.
fuente
Cree una plantilla de inclusión "intranet / nav_item.html":
E inclúyelo en el elemento de navegación:
Y necesitas agregar esto a la configuración:
fuente
aquí hay una solución bastante simple, https://github.com/hellysmile/django-activeurl
fuente
de esta pregunta SO
Repita según sea necesario para cada enlace.
fuente
/blog/posts/2021/04/12
fuera la URL, el elemento / blog / nav estaría activo.Questions
,Tags
,Users
,Badges
,Unanswered
,Ask Question
. no funcionaráQuestions
, pero para todas las demás navegaciones funcionará bien.También utilicé jQuery para resaltarlo y lo encontré más elegante que abarrotar la plantilla con etiquetas de plantilla Django no semánticas.
El siguiente código funciona con menús desplegables anidados en bootstrap 3 (destaca tanto el elemento principal como el secundario
<li>
.También es bastante fácil agregar un
click
evento areturn false
(o cambiar elhref
atributo a#
) para la página actual, sin cambiar la plantilla / marcado html:fuente
Utilizo una combinación de este mixin para vistas basadas en clases:
con esto en la plantilla:
fuente
El mío es un poco similar a otro enfoque JS presentado anteriormente ... solo que sin jQuery ...
Digamos que tenemos en base.html lo siguiente:
Acabo de hacer mi jerarquía para seguir un cierto patrón de URL ... después de la dirección de host ... tengo mi categoría principal, por ejemplo, casa, noticias, análisis, etc. y la expresión regular solo saca la primera palabra de la ubicación
fuente