在Django模板中执行getattr()样式查找

Python的getattr()方法在您事先不知道某个属性的名称时非常有用。

这个function也可以在模板中派上用场,但是我从来没有想过要做到这一点。 是否有可以执行dynamic属性查找的内置标签或非内置标签?

我最近还必须将这些代码作为自定义模板标签来编写 。 为了处理所有查找场景,它首先执行标准属性查找,然后尝试执行字典查找,然后尝试getitem查找(用于列表工作),然后遵循标准Django模板行为。未find。

(2009-08-26更新,现在也处理列表索引查找)

# 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) 

模板用法:

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

我不这么认为。 但是编写自定义模板标签来返回上下文字典中的属性并不难。 如果你只是想返回一个string,尝试这样的事情:

 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) 

请注意,在您的视图中而不是在模板中执行此操作可能同样简单,除非这是您的数据中经常重复的条件。

我结束了为有问题的模型添加一个方法,该方法可以像模板中的属性一样访问。

尽pipe如此,如果内置标签允许您dynamic查找属性,我认为这将会很好,因为这是我们在模板中经常遇到的一个问题。

保持get和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 

没有内置标签,但编写自己的代码不是太难。

这段代码保存了我的一天,但我需要它跨越关系,所以我改变了它分裂的arg“。 并recursion获得价值。 它可以在一行中完成: return getattribute(getattribute(value,str(arg).split(".")[0]),".".join(str(arg).split(".")[1:]))但为了便于阅读,我把它留在了4中。 我希望有人用这个。

 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)