what websites spa react framework creating and django django-templates

websites - redux django



¿Cómo renderizar el menú con un elemento activo con DRY? (9)

Usando etiqueta de plantilla

Simplemente puede usar la siguiente etiqueta de plantilla:

# path/to/templatetags/mytags.py import re from django import template from django.core.urlresolvers import reverse, NoReverseMatch register = template.Library() @register.simple_tag(takes_context=True) def active(context, pattern_or_urlname): try: pattern = ''^'' + reverse(pattern_or_urlname) except NoReverseMatch: pattern = pattern_or_urlname path = context[''request''].path if re.search(pattern, path): return ''active'' return ''''

Entonces, en ti tu plantilla:

{% load mytags %} <nav><ul> <li class="nav-home {% active ''url-name'' %}"><a href="#">Home</a></li> <li class="nav-blog {% active ''^/regex/'' %}"><a href="#">Blog</a></li> </ul></nav>

Usando solo HTML y CSS

Existe otro enfoque, que utiliza solo HTML y CSS, que puede usar en cualquier marco de trabajo o sitios estáticos.

Teniendo en cuenta que tienes un menú de navegación como este:

<nav><ul> <li class="nav-home"><a href="#">Home</a></li> <li class="nav-blog"><a href="#">Blog</a></li> <li class="nav-contact"><a href="#">Contact</a></li> </ul></nav>

Cree algunas plantillas base, una para cada sesión de su sitio, como por ejemplo:

home.html base_blog.html base_contact.html

Todas estas plantillas extienden base.html con una "sección" de bloque , como por ejemplo:

... <body id="{% block section %}section-generic{% endblock %}"> ...

Luego, tomando el ejemplo de base_blog.html , debe tener lo siguiente:

{% extends "base.html" %} {% block section %}section-blog{% endblock %}

Ahora es fácil definir el elemento del menú activado utilizando solo CSS:

#section-home .nav-home, #section-blog .nav-blog, #section-contact .nav-contact { background-color: #ccc; }

Me gustaría renderizar construcciones como:

<a href=''/home''>Home</a> <span class=''active''>Community</span> <a href=''/about''>About</a>

Donde se selecciona Comunidad elemento de menú. Tengo un menú con las mismas opciones para varias plantillas, pero no me gustaría crear combinaciones para cada plantilla:

<!-- for Home template--> <span class=''active''>Home</span> <a href=''/comminuty''>Community</a> <a href=''/about''>About</a> ... <!-- for Community template--> <a href=''/home''>Home</a> <span class=''active''>Community</span> <a href=''/about''>About</a> ... <!-- for About template--> <a href=''/home''>Home</a> <a href=''/community''>Community</a> <span class=''active''>About</span>

Tenemos una lista permanente de elementos del menú, por lo tanto, puede ser una forma más efectiva: crear solo una estructura generalizada del menú y luego renderizar el menú con la opción requerida para la plantilla.

Por ejemplo, podría ser una etiqueta que permita hacer eso.


Basado en la respuesta de @ vincent, hay una forma más fácil de hacerlo sin alterar los patrones de url de django.

La ruta de solicitud actual se puede comparar con la ruta del elemento de menú representado, y si coinciden, este es el elemento activo.

En el siguiente ejemplo, uso django-mptt para representar el menú, pero uno puede reemplazar node.path con cada ruta del elemento de menú.

<li class="{% if node.path == request.path %}active{% endif %}"> <a href="node.path">node.title</a> </li>


Encontré una solución DRY fácil y elegante.

Es el fragmento: http://djangosnippets.org/snippets/2421/

**Placed in templates/includes/tabs.html** <ul class="tab-menu"> <li class="{% if active_tab == ''tab1'' %} active{% endif %}"><a href="#">Tab 1</a></li> <li class="{% if active_tab == ''tab2'' %} active{% endif %}"><a href="#">Tab 2</a></li> <li class="{% if active_tab == ''tab3'' %} active{% endif %}"><a href="#">Tab 3</a></li> </ul> **Placed in your page template** {% include "includes/tabs.html" with active_tab=''tab1'' %}


Entendí otra forma de hacerlo, lo suficientemente elegante gracias a esta respuesta: https://.com/a/17614086/34871

Dado un patrón de URL como:

url(r''^some-url'', "myapp.myview", name=''my_view_name''),

my_view_name está disponible para la plantilla a través de la request (recuerde que necesita usar un RequestContext, que está implícito al usar render_to_response)

Entonces los elementos del menú pueden verse así:

<li class="{% if request.resolver_match.url_name == "my_view_name" %}active{% endif %}"><a href="{% url "my_view_name" %}">Shortcut1</a></li> <li class="{% if request.resolver_match.url_name == "my_view_name2" %}active{% endif %}"><a href="{% url "my_view_name2" %}">Shortcut2</a></li>

etc.

De esta manera, la url puede cambiar y aún funciona si los parámetros de la url varían, y no es necesario mantener una lista de elementos de menú en otro lugar.


Estoy usando una solución CSS más fácil y pura. Tiene sus limitaciones, de las que sé y con las que puedo vivir, pero evita los torpes selectores de clases CSS, como este:

<a href="index.html" class="item{% if url == request.path %}active{% endif %}">index</a>

Debido a que falta un carácter de espacio antes de active al selector de clase se le llama itemactive lugar de item active y esto no es exactamente demasiado difícil como para equivocarse.

Para mí, esta solución de CSS puro funciona mucho mejor:

a.item /* all menu items are of this class */ { color: black; text-decoration: none; } a.item[href~="{{ request.path }}"] /* just the one which is selected matches */ { color: red; text-decoration: underline; }

Aviso: Esto incluso funciona si la URL tiene componentes de ruta adicionales, porque href también coincide parcialmente. Eso eventualmente podría causar ''colisiones'' con más de una coincidencia, pero a menudo simplemente funciona, porque en sitios web bien estructurados, un "subdirectorio" de una URL normalmente es un elemento secundario del elemento de menú seleccionado.


He encontrado una manera de utilizar etiquetas de bloque dentro de la plantilla principal que contiene el menú para lograr algo como esto.

base.html - la plantilla principal:

<a href="/" class="{% block menu_home_class %}{% endblock %}">Home</a> <a href="/about" class="{% block menu_about_class %}{% endblock %}">About</a> <a href="/contact" class="{% block menu_contact_class %}{% endblock %}">Contact</a> {% block content %}{% endblock %}

about.html - plantilla para una página específica:

{% extends "base.html" %} {% block menu_about_class %}active{% endblock %} {% block content %} About page content... {% endblock %}

Como puede ver, lo que varía entre las diferentes plantillas de página es el nombre del bloque que contiene active . contact.html usaría menu_contact_class , y así sucesivamente.

Una ventaja de este enfoque es que puede tener varias subpáginas con el mismo elemento de menú activo. Por ejemplo, una página acerca de puede tener subpáginas que proporcionan información sobre cada miembro del equipo de una empresa. Podría tener sentido que el elemento del menú Acerca de permanezca activo para cada una de estas subpáginas.


Hoy me encontré con este desafío sobre cómo activar dinámicamente una "categoría" en una barra lateral. Las categorías tienen babosas que son de la base de datos.

Lo resolví comprobando que la categoría slug estaba en la ruta actual. Las babosas son únicas (práctica estándar) así que creo que esto debería funcionar sin ningún conflicto.

{% if category.slug in request.path %}active{% endif %}

Código de ejemplo completo del ciclo para obtener las categorías y activar el actual.

{% for category in categories %} <a class="list-group-item {% if category.slug in request.path %}active{% endif %}" href="{% url ''help:category_index'' category.slug %}"> <span class="badge">{{ category.article_set.count }}</span> {{ category.title }} </a> {% endfor %}


Podría hacer una variable de contexto con el nombre, la URL y si es un elemento activo:

{% for name, url, active in links %} {% if active %} <span class=''active''>{{ name }}</span> {% else %} <a href=''{{ url }}''>{{ name }}</a> {% endif %} {% endfor %}

Si este menú está presente en todas las páginas, puede usar un procesador de contexto:

def menu_links(request): links = [] # write code here to construct links return { ''links'': links }

Luego, en su archivo de configuración, agregue esa función a TEMPLATE_CONTEXT_PROCESSORS como sigue: path.to.where.that.function.is.located.menu_links . Esto significa que se llamará a la función menu_links para cada plantilla y eso significa que los links variables están disponibles en cada plantilla.


Suponiendo que el elemento de navegación es un enlace con la misma URL que la página actual, puede usar JavaScript. Aquí hay un método anotado que uso para agregar un class="active" a un li en un menú de navegación con class="nav" :

// Get the path name (the part directly after the URL) and append a trailing slash // For example, ''http://www.example.com/subpage1/sub-subpage/'' // would become ''/subpage1/'' var pathName = ''/'' + window.location.pathname.split(''/'')[1]; if ( pathName != ''/'' ) { pathName = pathName + ''/''; } // Form the rest of the URL, so that we now have ''http://www.example.com/subpage1/'' // This returns a top-level nav item var url = window.location.protocol + ''//'' + window.location.host + pathName; console.log(url); // Add an ''active'' class to the navigation list item that contains this url var $links = document.querySelectorAll(''.nav a''); $link = Array.prototype.filter.call( $links, function(el) { return el.href === url; })[0]; $link.parentNode.className += '' active'';

Este método significa que simplemente puede colocarlo en su plantilla base una vez y olvidarse de él. Sin repetición y sin especificación manual de la URL de la página en cada plantilla.

Una advertencia: esto obviamente solo funciona si la url encontrada coincide con un enlace de navegación href . También sería posible especificar un par de casos de uso especial en el JS, o dirigirse a un elemento padre diferente según sea necesario.

Aquí hay un ejemplo ejecutable (recuerde, los fragmentos se ejecutan en StackSnippets):

// Get the path name (the part directly after the URL) and append a trailing slash // For example, ''http://www.example.com/subpage1/sub-subpage/'' // would become ''/subpage1/'' var pathName = ''/'' + window.location.pathname.split(''/'')[1]; if ( pathName != ''/'' ) { pathName = pathName + ''/''; } // Form the rest of the URL, so that we now have ''http://www.example.com/subpage1/'' // This returns a top-level nav item var url = window.location.protocol + ''//'' + window.location.host + pathName; console.log(url); // Add an ''active'' class to the navigation list item that contains this url var $links = document.querySelectorAll(''.nav a''); $link = Array.prototype.filter.call( $links, function(el) { return el.href === url; })[0]; $link.parentNode.className += '' active'';

li { display: inline-block; margin: 0 10px; } a { color: black; text-decoration: none; } .active a { color: red; }

<ul class="nav"> <li> <a href="http://example.com/">Example Link</a> </li> <li> <a href="http://stacksnippets.net/js/">This Snippet</a> </li> <li> <a href="https://google.com/">Google</a> </li> <li> <a href="http://.com/"></a> </li> </ul>