Ten fragment uratował mi dzień, ale potrzebowałem go, by objąć go relacjami, więc zmieniłem go, aby podzielić argument na "." i rekursywnie uzyskać wartość. Można to zrobić w jednym wierszu: return getattribute(getattribute(value,str(arg).split(".")[0]),".".join(str(arg).split(".")[1:]))
, ale zostawiłem go na 4 dla czytelności. Mam nadzieję, że ktoś do tego użyje.
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)
Zastanawiam się, czy próbujesz zrobić za dużo w swoich szablonach. getattr czasami czuje się jak czarna magia w kodzie Pythona, więc z pewnością jest to zapach kodu w szablonie! –