Realizar una búsqueda de estilo getattr () en una plantilla de django

El método getattr () de Python es útil cuando no conoce el nombre de un determinado atributo de antemano.

Esta funcionalidad también sería útil en las plantillas, pero nunca he encontrado una manera de hacerlo. ¿Hay una etiqueta incorporada o no incorporada que pueda realizar búsquedas de atributos dynamics?

También tuve que escribir este código como una etiqueta de plantilla personalizada recientemente. Para manejar todos los escenarios de búsqueda, primero realiza una búsqueda de atributos estándar, luego trata de hacer una búsqueda en el diccionario, luego intenta una búsqueda getitem (para que las listas funcionen), luego sigue el comportamiento estándar de la plantilla Django cuando un objeto está extraviado.

(actualizado el 2009-08-26 para ahora manejar las búsquedas de índice de lista también)

# app/templatetags/getattribute.py import re from django import template from django.conf import settings numeric_test = re.compile("^\d+$") register = template.Library() def getattribute(value, arg): """Gets an attribute of an object dynamically from a string name""" if hasattr(value, str(arg)): return getattr(value, arg) elif hasattr(value, 'has_key') and value.has_key(arg): return value[arg] elif numeric_test.match(str(arg)) and len(value) > int(arg): return value[int(arg)] else: return settings.TEMPLATE_STRING_IF_INVALID register.filter('getattribute', getattribute) 

Uso de la plantilla:

 {% load getattribute %} {{ object|getattribute:dynamic_string_var }} 

No lo creo. Pero no sería demasiado difícil escribir una etiqueta de plantilla personalizada para devolver un atributo en el dictado de contexto. Si simplemente estás tratando de devolver una cadena, intenta algo como esto:

 class GetAttrNode(template.Node): def __init__(self, attr_name): self.attr_name = attr_name def render(self, context): try: return context[self.attr_name] except: # (better yet, return an exception here) return '' @register.tag def get_attr(parser, token): return GetAttrNode(token) 

Tenga en cuenta que probablemente sea tan fácil hacer esto en su vista en lugar de en la plantilla, a menos que esta sea una condición que se repita a menudo en sus datos.

Terminé agregando un método al modelo en cuestión, y se puede acceder a ese método como un atributo en la plantilla.

Aún así, creo que sería genial si una etiqueta integrada le permitiera buscar un atributo dinámicamente, ya que este es un problema que muchos de nosotros tenemos constantemente en nuestras plantillas.

Manteniendo la distinción entre get y getattr,

 @register.filter(name='get') def get(o, index): try: return o[index] except: return settings.TEMPLATE_STRING_IF_INVALID @register.filter(name='getattr') def getattrfilter(o, attr): try: return getattr(o, attr) except: return settings.TEMPLATE_STRING_IF_INVALID 

No hay una etiqueta incorporada, pero no debería ser demasiado difícil escribir la tuya .

Ese fragmento salvó mi día, pero lo necesitaba para abarcar las relaciones, así que lo cambié para dividir el argumento por “.” y recursivamente obtener el valor. Se podría hacer en una línea: return getattribute(getattribute(value,str(arg).split(".")[0]),".".join(str(arg).split(".")[1:])) pero lo dejé en 4 por legibilidad. Espero que alguien tenga uso para esto.

 import re from django import template from django.conf import settings numeric_test = re.compile("^\d+$") register = template.Library() def getattribute(value, arg): """Gets an attribute of an object dynamically AND recursively from a string name""" if "." in str(arg): firstarg = str(arg).split(".")[0] value = getattribute(value,firstarg) arg = ".".join(str(arg).split(".")[1:]) return getattribute(value,arg) if hasattr(value, str(arg)): return getattr(value, arg) elif hasattr(value, 'has_key') and value.has_key(arg): return value[arg] elif numeric_test.match(str(arg)) and len(value) > int(arg): return value[int(arg)] else: #return settings.TEMPLATE_STRING_IF_INVALID return 'no attr.' + str(arg) + 'for:' + str(value) register.filter('getattribute', getattribute)