python - safe - linebreaksbr django
Realización de una búsqueda de estilo getattr() en una plantilla django (6)
El método getattr () de Python es útil cuando no se conoce el nombre de un determinado atributo por adelantado.
Esta funcionalidad también sería útil en las plantillas, pero nunca he encontrado la manera de hacerlo. ¿Hay una etiqueta incorporada o una etiqueta no incorporada que pueda realizar búsquedas dinámicas de atributos?
Ese fragmento me salvó el día, pero necesitaba que se extendiera sobre 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 para facilitar la lectura. 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)
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 suya .
No lo creo. Pero no sería demasiado difícil escribir una etiqueta de plantilla personalizada para devolver un atributo en el contexto dict. Si simplemente intentas devolver una cadena, prueba 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 repite a menudo en sus datos.
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 intenta 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 se trata de un objeto extraviado.
(actualizado 2009-08-26 para manejar ahora 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 }}
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 permitiera buscar dinámicamente un atributo, ya que este es un problema que muchos de nosotros tenemos constantemente en nuestras plantillas.