Jugando con __getattribute__ y Django

Siguiento mi pequeño experimento de pseudoclases-dicionario para facilitarme la vida con Django, se me ocurrió una forma de poder establecer y recoger valores de variable directamente desde las plantillas de Django.

El motor de plantillas de Django, por una acertada decisión de diseño, hizo a bien de no incluir la posibilidad de establecer variables o ejecutar métodos en su motor de plantillas, al igual que ocurre por ejemplo con Smarty (motor de plantillas para PHP).

Sin embargo, dada la gran potencia de Python, existe una forma de hacerlo, muy limitada pero efectiva, sobrecargando el método __getattribute__ .

# Importamos compile del modulo de expresiones regulares
from re import compile as rec

# Declaramos la expresion regular que identifica los nombres de propiedad
gs = rec("^(get_(.*))|(set_(.*)_(.*))|(setn_(.*)_(\d+))|(setb_(.*)_(true|True|false|False|0|1|-1))$")
class Strangelet(dict):
''' Clase que permite la asignacion con nombres de propiedad '''
def __getattribute__(self,x):
# Sobrecargamos el metodo que pide los atributos
a = gs.match(x)
if a: # Si cumple la expresion regular
a=a.groups()
if a[0]:
# Primer caso, devolvemos valor
return dict.__getitem__(self, a[1])
elif a[2]:
# Segundo caso, establecemos valor como cadena
dict.__setitem__(self, a[3], a[4])
elif a[5]:
# Tercer caso, establecemos valor como entero
dict.__setitem__(self, a[6], int(a[7]))
elif a[8]:
# Cuarto caso, establecemos valor como booleano
# muy util para trabajar con los IF de Django
dict.__setitem__(self, a[9], a[10] in ("true","True","1","-1"))
# Retornamos cadena vacia, para no mostrar nada
return ""
# se podria retornar None, pero Django los muestra.
else:
# Si no se cumple la expresion regular, usamos el metodo heredado
return dict.__getattribute__(self,x)

if __name__ == "__main__":
# Test de unidad
a = Strangelet()
a.setb_var_0
print a.get_var
a.setb_var_True
print a.get_var
a.setn_var_1
print a.get_var
a.set_text_EstoEsUnTexto
print a.get_text

Y podríamos usarlo para asignar variables en Django:

{{ instancia_strangelet.setn_variable_1 }}
{% ifequal instancia_strangelet.get_variable 1 %}¡Es igual a uno!{% endifequal %}
{{ instancia_strangelet.setb_variable_false }}
{% if instancia_strangelet.get_variable %}No pasará por aquí.{% else %}¡Y ahora es False!{% endif %}

Que en efecto mostraría:

¡Es igual a uno! ¡Y ahora es False!

Todo esto es posible porque Django respeta los __getattribute__ de las clases, al ser puramente Python. ¿Divertido, eh?

Python no tiene getters ni setters, pero ni falta que le hace.

Aviso que este experimento es sólo eso, un experimento, no apto para entornos de producción o proyectos serios, y es una aberración contra la naturaleza tanto de Python como del motor de plantillas de Django. Pero es curioso, eso sí.

0 comentarios:

Publicar un comentario en la entrada