Django es el entorno de desarrollo web para perfeccionistas con límites de tiempo

Entradas sobre "snippets":

Subdominios con Django

En ocasiones nos interesa trabajar con subdominios en nuestros proyectos Django. Para ello podemos utilizar un sencillo middleware para subdominios que podemos encontrar en djangosnippets. Basta con guardarlo en nuestro proyecto e incluirlo en la lista MIDDLEWARE_CLASSES de nuestro settings.py. De esta forma tendremos el subdominio de la petición en la variable subdomain del objeto request.

El problema al trabajar con subdominios es que las sesiones iniciadas en un subdominio no se mantienen cuando se cambia a otro. Para poder mantener activas las sesiones entre subdominios tenemos que añadir la siguiente línea al settings.py de nuestro proyecto:

SESSION_COOKIE_DOMAIN = '.mi-dominio.com'

De esta forma la cookie de sesión que se almacena en el navegador valdrá para todos los subdominios.

Subdominios para usuarios

Si por ejemplo queremos dar un subdominio a cada usuario de nuestro proyecto podemos modificar el middleware para que busque el usuario adecuado y lo incluya en el objeto request. El middleware quedaría de la siguiente manera:

from django.http import Http404
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User

class SubdomainMiddleware:
    """ Make the subdomain publicly available to classes """

    def process_request(self, request):
        domain_parts = request.get_host().split('.')
        if (len(domain_parts) > 2):
            subdomain = domain_parts[0]
            if (subdomain.lower() == 'www'):
                subdomain = ''
            domain = '.'.join(domain_parts[1:])
        else:
            subdomain = ''
            domain = request.META['HTTP_HOST']

        request.subdomain = subdomain
        request.domain = domain

        if subdomain != 'www' and subdomain != '':
            # Buscamos el usuario del subdominio
            try:
                request.usuario_subdominio = User.objects.filter(username=subdomain)
            except ObjectDoesNotExist:
                raise Http404

De esta forma el usuario correspondiente al subdominio que se visita está disponible en la variable usuario_subdominio del objeto request. Si utilizamos variables de contexto y tenemos 'django.core.context_processors.request' en la lista de procesadores de contexto (setting TEMPLATE_CONTEXT_PROCESSORS) podemos obtener el usuario actual en nuestras plantillas mediante:

{{ request.usuario_subdominio }}

Publicado por Antonio Melé el Sunday 2 de August de 2009 | 4 comentarios | Categorías: middleware, snippets, trucos, urls

Templatetag {% if %} con más comparaciones

Este snippet reemplaza la funcionalidad del templatetag {% if %} permitiendo realizar comparaciones con operadores >, <, >=, <=, != además de las comparaciones que permite hacer {% if %} por defecto. Por ejemplo una comparación con el operador mayor-igual-que para mostrar algo si hay más de 5 artículos sería:

{% if articulos|length >= 5 %} ... {% endif %}

Para utilizarlo en nuestro proyecto nos basta con seguir los siguientes pasos:

  1. Descargamos smart_if desde djangosnippets.
  2. Lo guardamos como smart_if.py en la carpeta templatetags de alguna de las aplicaciones de nuestro proyecto.
  3. Añadimos el tag {% load smartif %} en las plantillas que queramos utilizarlo y listo.

También hay otro snippet, elif for smart if tag, que permite utilizar el tag {% elif %} para realizar otras comparaciones dentro de un bucle if con nuestro tag smart_if. Este snippet incluye sólo la función smart_if para que la reemplacemos en nuestro smart_if.py original.

Publicado por Antonio Melé el Sunday 19 de July de 2009 | 1 comentario | Categorías: plantillas, snippets, templatetags, trucos

Templatetags globales en nuestros proyectos Django

Los templatetags de Django son a nivel de aplicación. Sin embargo a veces nos gustaría que distintas aplicaciones compartieran templatetags ó evitarnos tener que cargarlos en todas las plantillas mediante {% load ... %}.

Este sencillo snippet muestra cómo registrar templatetags de modo global para todo el proyecto gracias a la función add_to_builtins de django.template.

Para crear templatetags globales haremos lo siguiente:

  1. Creamos un directorio en el que copiamos todos los templatetags que queramos utilizar de forma global (en sus archivos .py correspondientes). Por ejemplo un directorio globaltags/.

  2. Añadimos al directorio un archivo __init__.py en el que cargamos los templatetags que queramos a nivel global de la siguiente manera:

    from django.template import add_to_builtins
    
    add_to_builtins('globaltags.mi_template_tag_1')
    add_to_builtins('globaltags.mi_template_tag_2')
    
  3. Añadimos dicho directorio al setting INSTALLED_APPS como si se tratara de una aplicación más instalada en nuestro proyecto.

Siguiendo estos pasos podemos utilizar en cualquier plantilla los templatetags que hayamos registrado globalmente y sin tener que cargarlos mediante {% load ... %}.

Publicado por Antonio Melé el Tuesday 31 de March de 2009 | 1 comentario | Categorías: snippets, templatetags, trucos

Snippet de vista para i18n

Una de las cosas que nos ofrece Django es vistas genéricas y soporte para localización (aka i10n) e internacionalización (aka i18n). Entonces una vez tenemos nuestro sitio con i18n o i10n pues lo que sigue es que le demos a nuestros usuarios la manera de escoger su idioma, Django tiene un algoritmo par esto, sin embargo en algún punto nuestros usuarios querrán poder escoger su idioma preferido, para esto este framework nos da la opcion de una vista generica, sobre la cual encontraréis información en http://docs.djangoproject.com/en/dev/topics/i18n/#the-set-language-redirect-view.

Lo único es que esta vista espera que haya un formulario para que el usuario escoja su idioma y además que tengamos predefinida una página a la cual el usuario será redirigido después de seleccionar el idioma a lo cual le veo particularmente un inconveniente, pues si el usuario ha llegado a un punto importante para él y es llevado a la página inicial no le agradará (en mi caso me molestaría). Además, ¿y si queremos tener la posibilidad de hacerlo desde una url y no una variable por post?

Para resolver este conflicto se modifica un poco la vista que nos trae Django y la dejamos así:

def set_lang(request,lang):
   response = HttpResponseRedirect(request.META['HTTP_REFERER'])
   lang_code = u'%s' % lang
   if lang_code and check_for_language(lang_code):
      if hasattr(request, 'session'):
         request.session['django_language'] = lang_code
      else:
         response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
return response

Esta vista espera que se escoja el idioma por una url y además redireccionará al usuario a la página en la que se encontraba, podemos hacerlo incluso en el urls.py y finalmente escogemos la url:

urlpatterns = patterns('',
   ...
   (r'^set_lang/(?P<lang>\w{2})/$',set_lang),
   ...
)

De esta manera si se va a /set_lang/es/ Django cargará todo nuestro sitio en español y volvera a la vista en la que lo hayamos hecho.

Publicado por Diego Andrés el Friday 20 de March de 2009 | 2 comentarios | Categorías: internacionalización, snippets, traducciones, trucos